P3769 [CH弱省胡策R2]TATT

qq_45323960發表於2020-11-20

題目描述
四維空間真是美妙。 現在有 n n n 個四維空間中的點,請求出一條最長的路徑,滿足任意一維座標都是單調不降的。 注意路徑起點是任意選擇的,並且路徑與輸入順序無關(路徑順序不一定要滿足在輸入中是升序)。

路徑的長度是經過的點的數量,任意點只能經過一次。

輸入格式
第一行一個整數 n n n 。 接下來 n n n 行,每行四個整數 a i , b i , c i , d i a_i,b_i,c_i,d_i ai,bi,ci,di 。表示四維座標

輸出格式
一行一個整數,表示最長路徑的長度

輸入輸出樣例
輸入 #1

4
2 3 33 2333
2 3 33 2333
2 3 33 2333
2 3 33 2333

輸出 #1

4
#include<bits/stdc++.h>

using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 5e4 + 10, D = 3;
const double alpha = 0.75;


struct K_D_Tree {
    int d[N], lc[N], rc[N];
    struct node {
        int x[D], mx;
    } p[N];
    int g[N], siz[N], mx[N], rt;
    int MX[N][D], MN[N][D];
    double av[D], va[D];

    inline void update(int x) {
        siz[x] = siz[lc[x]] + siz[rc[x]] + 1, mx[x] = p[x].mx;
        memcpy(MN[x], p[x].x, sizeof(p[x].x));
        memcpy(MX[x], p[x].x, sizeof(p[x].x));
        if (lc[x])
            for (int i = 0; i <= D - 1; ++i) {
                MN[x][i] = min(MN[x][i], MN[lc[x]][i]);
                MX[x][i] = max(MX[x][i], MX[lc[x]][i]);
                mx[x] = max(mx[x], mx[lc[x]]);
            }
        if (rc[x])
            for (int i = 0; i <= D - 1; ++i) {
                MN[x][i] = min(MN[x][i], MN[rc[x]][i]);
                MX[x][i] = max(MX[x][i], MX[rc[x]][i]);
                mx[x] = max(mx[x], mx[rc[x]]);
            }
    }

    int build(int l, int r) {
        if (l > r)return 0;
        int mid = (l + r) >> 1;
        for (int i = 0; i <= D - 1; ++i)av[i] = va[i] = 0;
        for (int i = l; i <= r; ++i)
            for (int j = 0; j <= D - 1; ++j)
                av[j] += p[g[i]].x[j];
        for (int i = 0; i <= D - 1; ++i)av[i] /= 1.0 * (r - l + 1);
        for (int i = l; i <= r; ++i)
            for (int j = 0; j <= D - 1; ++j)
                va[j] += (p[g[i]].x[j] - av[j]) * (p[g[i]].x[j] - av[j]);
        int dim = max_element(va, va + D) - va;
        nth_element(g + l, g + mid, g + r + 1, [&](int i, int j) {
            return p[i].x[dim] < p[j].x[dim];
        }), d[g[mid]] = dim;
        lc[g[mid]] = build(l, mid - 1), rc[g[mid]] = build(mid + 1, r);
        update(g[mid]);
        return g[mid];
    }

    int q[N];

    void insert(int &x, int v) {
        if (!x)return update(x = v), void();
        insert((p[v].x[d[x]] <= p[x].x[d[x]] ? lc : rc)[x], v);
        update(x);
        if (alpha * siz[x] <= (double) max(siz[lc[x]], siz[rc[x]])) {
            int t = 0, l = 1, r = 1;
            q[1] = x;
            while (l <= r) {
                int u = g[++t] = q[l++];
                if (lc[u])q[++r] = lc[u];
                if (rc[u])q[++r] = rc[u];
            }
            x = build(1, t);
        }
    }

    int ans;

    void ask(int x, int v) {
        if (mx[x] <= ans)return;
        bool in = true, out = false;
        for (int i = 0; i <= D - 1; ++i) {
            if (p[v].x[i] < MX[x][i])in = false;
            if (p[v].x[i] < MN[x][i])out = true;
        }
        if (out)return;
        if (in)return ans = mx[x], void();
        bool flag = true;
        for (int i = 0; i <= D - 1; ++i)
            if (p[v].x[i] < p[x].x[i]) {
                flag = false;
                break;
            }
        if (flag)ans = max(ans, p[x].mx);
        ask(lc[x], v), ask(rc[x], v);
    }
} K;

int n, ans;
int a[N][D + 1], id[N];

int main() {
    n = qr();
    for (int i = 1; i <= n; ++i)
        for (int j = 0; j <= D; ++j)
            a[i][j] = qr();
    iota(id + 1, id + 1 + n, 1);
    sort(id + 1, id + 1 + n, [&](int i, int j) {
        for (int t = D; t >= 0; --t)
            if (a[i][t] != a[j][t])
                return a[i][t] < a[j][t];
        return false;
    });
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j <= D - 1; ++j)
            K.p[i].x[j] = a[id[i]][j];
        K.ans = 0, K.ask(K.rt, i);
        ans = max(ans, K.p[i].mx = K.ans + 1);
        K.insert(K.rt, i);
    }
    printf("%d\n", ans);
    return 0;
}

相關文章