_bzoj3224 Tyvj 1728 普通平衡树【Splay】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3224

保存splay模版

一刻不停写了一个小时多一点,幸好一遍过了!(其实带着freopen wa了一次)

添加一个易出bug的地方叭(鉴于曾经有次这么错过):此题平衡树里可以用重复值,我是用tm保存出现的次数,因此在求第k大时,千万小心循环结束条件!

#include <cstdio>
#include <algorithm>

const int maxn = 200005;

int fa[maxn], ch[maxn][2], key[maxn], tm[maxn], siz[maxn], root, cnt, t1, t2;

inline void pushup(int x) {
	siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + tm[x];
}
inline void rotate(int x) {
	int y = fa[x];
	if (y == ch[fa[y]][0]) {
		ch[fa[y]][0] = x;
	}
	else {
		ch[fa[y]][1] = x;
	}
	fa[x] = fa[y];
	int dir = x == ch[y][1];
	ch[y][dir] = ch[x][dir ^ 1];
	fa[ch[x][dir ^ 1]] = y;
	ch[x][dir ^ 1] = y;
	fa[y] = x;
	pushup(y);
	pushup(x);
}
inline void splay(int x) {
	int p, flag1, flag2;
	while (fa[x]) {
		p = fa[x];
		if (!fa[p]) {
			rotate(x);
		}
		else {
			flag1 = x == ch[p][1];
			flag2 = p == ch[fa[p]][1];
			if (flag1 ^ flag2) {
				rotate(x);
			}
			else {
				rotate(p);
			}
			rotate(x);
		}
	}
	root = x;
}
bool ist(int x, int val, int p, int dir) {
	if (!x) {
		key[++cnt] = val;
		tm[cnt] = 1;
		siz[cnt] = 1;
		fa[cnt] = p;
		ch[p][dir] = cnt;
		return true;
	}
	if (val < key[x]) {
		bool rt = ist(ch[x][0], val, x, 0);
		pushup(x);
		return rt;
	}
	else if (val > key[x]) {
		bool rt = ist(ch[x][1], val, x, 1);
		pushup(x);
		return rt;
	}
	else {
		++tm[x];
		++siz[x];
		return false;
	}
}
inline int fndmin(int x) {
	int rt = x, mn = key[x];
	for (int i = ch[x][0]; i; i = ch[i][0]) {
		if (mn > key[i]) {
			mn = key[rt = i];
		}
	}
	return rt;
}
inline int fndmax(int x) {
	int rt = x, mx = key[x];
	for (int i = ch[x][1]; i; i = ch[i][1]) {
		if (mx < key[i]) {
			mx = key[rt = i];
		}
	}
	return rt;
}
void del(int x, int value) {
	if (!x) {
		return;
	}
	if (value < key[x]) {
		del(ch[x][0], value);
		pushup(x);
	}
	else if (value > key[x]) {
		del(ch[x][1], value);
		pushup(x);
	}
	else if (tm[x] > 1) {
		--tm[x];
		--siz[x];
	}
	else {
		splay(x);
		fa[ch[x][0]] = fa[ch[x][1]] = 0;
		if (!ch[x][0]) {
			root = ch[x][1];
		}
		else if (!ch[x][1]) {
			root = ch[x][0];
		}
		else {
			root = fndmax(ch[x][0]);
			splay(root);
			fa[ch[x][1]] = root;
			ch[root][1] = ch[x][1];
			pushup(root);
		}
	}
}
inline int qianqu(int val) {
	if (ist(root, val, 0, 0)) {
		splay(cnt);
	}
	int x = root;
	while (val != key[x]) {
		x = ch[x][val > key[x]];
	}
	splay(x);
	x = key[fndmax(ch[x][0])];
	del(root, val);
	return x;
}
inline int houji(int val) {
	if (ist(root, val, 0, 0)) {
		splay(cnt);
	}
	int x = root;
	while (val != key[x]) {
		x = ch[x][val > key[x]];
	}
	splay(x);
	x = key[fndmin(ch[x][1])];
	del(root, val);
	return x;
}
inline int getrank(int val) {
	int x = root;
	while (key[x] != val) {
		x = ch[x][val > key[x]];
	}
	splay(x);
	return siz[ch[x][0]] + 1;
}
inline int getnum(int rank) {
	int x = root;
	while (rank <= siz[ch[x][0]] || rank > siz[ch[x][0]] + tm[x]) {
		if (rank <= siz[ch[x][0]]) {
			x = ch[x][0];
		}
		else {
			rank -= siz[ch[x][0]] + tm[x];
			x = ch[x][1];
		}
	}
	return key[x];
}

int main(void) {
	int n;
	scanf("%d", &n);
	while (n--) {
		scanf("%d%d", &t1, &t2);
		if (t1 == 1) {
			if (ist(root, t2, 0, 0)) {
				splay(cnt);
			}
		}
		else if (t1 == 2) {
			del(root, t2);
		}
		else if (t1 == 3) {
			printf("%d\n", getrank(t2));
		}
		else if (t1 == 4) {
			printf("%d\n", getnum(t2));
		}
		else if (t1 == 5) {
			printf("%d\n", qianqu(t2));
		}
		else {
			printf("%d\n", houji(t2));
		}
	}
	return 0;
}

  

posted @ 2016-12-08 22:21  ciao_sora  阅读(221)  评论(0编辑  收藏  举报