1. 程式人生 > >Tsinsen A1210 光稜坦克——動態規劃+字首和優化

Tsinsen A1210 光稜坦克——動態規劃+字首和優化

題意

  • 一個平面直角座標系上,有N個點,標號為1到N,其中第i個點的座標為(x[i], y[i])。   求滿足以下兩個條件的點列{p[i]}的數目(假設{p[i]}的長度為M)   (1) 對任意1 <= i < j <= M,必有y[p[i]] > y[p[j]];   (2) 對任意3 <= i <= M,必有x[p[i-1]] < x[p[i]] < x[p[i-2]]或者x[p[i-2]] < x[p[i]] < x[p[i-1]]。   求滿足條件的非空序列{p[i]}的數目,結果對一個整數Q取模。

對於第一個限制很容易會想到對y

y進行排序

但是這樣子空間是O(n2)O(n^2)的,過不了這個卡空間的題

那麼我們考慮對xx進行排序

f[i][0/1]f[i][0/1]ii號點起始

向左或向右延伸的方案數

那麼我們每次新增一個新點一定是橫座標最大的

那麼它只能放在第一個或者第二個

那麼我們列舉這個點前面的點

如果它的縱座標小於當前新加的點 那麼當前點就是第一個點

那麼我們把列舉點右邊的點全部加入當前點的左邊

如果它的縱座標大於當前新加的點 列舉點就是第一個點

我們把當前點左邊的點全部加入列舉點的右邊

然後就做完了 時間複雜度O(n2)O(n^2)空間複雜度O(n)O(n)

Codes

#include<bits/stdc++.h>
#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
#define For(i, a, b) for(register int i = (a), i##_end_ = (b); i <= i##_end_; ++ i)
#define FOR(i, a, b) for(register int i = (a), i##_end_ = (b); i >= i##_end_; -- i)
#define debug(x) cout << #x << " = " << x << endl #define mem(a, b) memset(a, b, sizeof(a)) #define cpy(a, b) memcpy(a, b, sizeof(a)) #define min(a, b) (a < b ? a : b) #define max(a, b) (b < a ? a : b) #define inf (0x3f3f3f3f) #define INF (1e18) #define pb push_back #define mp make_pair #define x first #define y second typedef unsigned long long ull; typedef unsigned int uint; typedef long long ll; typedef std::pair<ll, int> PLI; typedef std::pair<int, int> PII; typedef long double ldb; typedef double db; template<class T>inline bool chkmax(T &_, T __) {return _ < __ ? _ = __, 1 : 0;} template<class T>inline bool chkmin(T &_, T __) {return _ > __ ? _ = __, 1 : 0;} using namespace std; const int N = 7e3 + 10; int f[N][2], n, ans, mod; struct Point { int x, y; bool operator < (const Point &T) const { return x < T.x; } }A[N]; int main() { #ifdef ylsakioi file("refract"); #endif scanf("%d%d", &n, &mod); For(i, 1, n) scanf("%d%d", &A[i].x, &A[i].y); ans = mod - n; sort(A + 1, A + n + 1); For(i, 1, n) { f[i][0] = f[i][1] = 1; FOR(j, i - 1, 1) { if(A[i].y > A[j].y) (f[i][0] += f[j][1]) %= mod; if(A[j].y > A[i].y) (f[j][1] += f[i][0]) %= mod; } } For(i, 1, n) (ans += (f[i][0] + f[i][1]) % mod) %= mod; cout << ans << endl; return 0; }