[Tsinsen A1210] 光棱坦克(動態規劃+前綴和優化)

題意

  • 一個平面直角座標系上,有NN個點,標號爲11NN,其中第ii個點的座標爲(x[i],y[i])(x[i], y[i]),求滿足以下兩個條件的點列p[i]{p[i]}的數目(假設p[i]{p[i]}的長度爲MM),一是對任意1i<jM1 \le i < j \le M,必有y[p[i]]y[p[i]] > y[p[j]]y[p[j]];二是對任意3iM3 \le i \le M,必有x[p[i1]]<x[p[i]]<x[p[i2]]x[p[i-1]] < x[p[i]] < x[p[i-2]]或者x[p[i2]]<x[p[i]]<x[p[i1]]x[p[i-2]] < x[p[i]] < x[p[i-1]]。求滿足條件的非空序列p[i]{p[i]}的數目,結果對一個整數QQ取模。

對於第一個限制很容易會想到對yy進行排序,但是這樣子空間是O(n2)O(n^2)的,過不了這個卡空間的題,那麼我們考慮對xx進行排序。

f[i][0/1]f[i][0/1]ii號點起始,向左或向右延伸的方案數,那麼我們每次添加一個新點一定是橫座標最大的,那麼它只能放在第一個或者第二個,那麼我們枚舉這個點前面的點,如果它的縱座標小於當前新加的點,那麼當前點就是第一個點,我們把枚舉點右邊的點全部加入當前點的左邊,如果它的縱座標大於當前新加的點,枚舉點就是第一個點,我們把當前點左邊的點全部加入枚舉點的右邊,時間複雜度O(n2)O(n^2),空間複雜度O(n)O(n)

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章