bzoj 3173 [Tjoi2013]最长上升子序列 splay

题面

题目传送门

解法

因为是\(1-n\)一个一个插入,所以每一次插入的时候只会对当前节点的答案产生影响,对于之前已经在序列中的不会有影响

所以只要动态维护这一个序列,并且维护子树中dp值的最大值

splay!!!!

时间复杂度:\(O(n\ log\ n)\)

代码

#include <bits/stdc++.h>
#define N 100010
using namespace std;
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
struct SplayTree {
    struct Node {
        int fa, siz, f, mx, child[2];
    } t[N];
    int tot, rt;
    bool son(int x, int y) {return (x == -1) ? false : (t[x].child[1] == y);}
    int siz(int x) {return (x == -1) ? 0 : t[x].siz;}
    int mx(int x) {return (x == -1) ? 0 : t[x].mx;}
    void Clear() {tot = rt = 0; t[0] = (Node) {-1, 1, 0, 0, -1, -1};}
    void Connect(int x, int y, int k) {
        if (x == -1) rt = y; else t[x].child[k] = y;
        if (y != -1) t[y].fa = x;
    }
    void update(int x) {
        if (x == -1) return;
        t[x].siz = 1 + siz(t[x].child[0]) + siz(t[x].child[1]);
        t[x].mx = max(mx(t[x].child[0]), max(mx(t[x].child[1]), t[x].f));
    }
    void Rotate(int x) {
        int y = t[x].fa, z = t[y].fa, a = son(y, x), b = !a;
        Connect(y, t[x].child[b], a);
        Connect(z, x, son(z, y));
        Connect(x, y, b);
        update(y), update(x);
    }
    void Splay(int x, int fa) {
        while (t[x].fa != fa) {
            int y = t[x].fa, z = t[y].fa;
            if (z != fa) {
                if (son(z, y) ^ son(y, x)) Rotate(x), Rotate(x);
                    else Rotate(y), Rotate(x);
            } else Rotate(x);
        }
    }
    int findkth(int k) {
        for (int now = rt; now != -1; ) {
            int tmp = siz(t[now].child[0]);
            if (k == tmp + 1) return now;
            if (k > tmp) k -= tmp + 1, now = t[now].child[1];
                else now = t[now].child[0];
        }
    }
    void Insert(int k) {
        int x = findkth(k + 1); Splay(x, -1);
        int y = t[x].child[1];
        t[++tot].fa = x, t[tot].siz = siz(y) + 1;
        t[tot].mx = t[tot].f = max(mx(t[x].child[0]), t[x].f) + 1;
        t[tot].child[0] = -1, t[tot].child[1] = y, t[x].child[1] = tot;
        if (y != -1) t[y].fa = tot;
        Splay(tot, -1);
    }
    int query() {return mx(rt);}
} T;
int main() {
    int n; read(n); T.Clear();
    for (int i = 1; i <= n; i++) {
        int x; read(x);
        T.Insert(x);
        cout << T.query() << "\n";
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/copperoxide/p/9478699.html