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

posted @ 2018-08-14 23:16  谜のNOIP  阅读(203)  评论(0编辑  收藏  举报