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;
}