用 fhq_Treap 实现可持久化平衡树

支持对历史版本进行操作的平衡树

Treap 和 Splay 都是旋来旋去的

这样平衡树可持久化听起来不太好搞?

还有 fhq_Treap !

每次涉及操作就复制一个节点出来

操作历史版本就继承它的根继续往下搞

在 Split 和 Merge 里加上有关可持久化的操作即可

这里因为写了根据权值来分割的 Split

所以就写比较传统的 getrank 了 = =

所以其他的一些涉及 Split 的操作都改了改

其实还是挺好写的

终于还是写了传引用的 Split

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cstdio>
#include<cmath>
#include<ctime>
#define lson t[cur].ch[0]
#define rson t[cur].ch[1]
using namespace std;

const int MAXN = 500001, inf = 0x7fffffff;

struct Node{
	int ch[2], siz, val, prio;
	Node(){ch[0] = ch[1] = siz = val = 0;}
}t[MAXN * 50];
int Root[MAXN], n, poolcur;

inline int rd() {
	register int x = 0;
	register char c = getchar();
	register bool f = false;
	while(!isdigit(c)) {
		if(c == '-') f = true;
		c = getchar();
	}
	while(isdigit(c)) {
		x = x * 10 + c - 48;
		c = getchar();
	}
	return f ? -x : x;
}
inline int newnode(int val) {
	register int cur = ++poolcur;
	t[cur].siz = 1;
	t[cur].prio = rand();
	t[cur].val = val;
	return cur;
}
inline void pushup(int cur) {
	t[cur].siz = t[lson].siz + t[rson].siz + 1;
	return;
}
void Split(int cur, int val, int &x, int &y) {
	if(!cur) x = y = 0;
	else {
		if(t[cur].val <= val) {
			x = ++poolcur; t[x] = t[cur];
			Split(t[x].ch[1], val, t[x].ch[1], y);
			pushup(x);
		} else {
			y = ++poolcur; t[y] = t[cur];
			Split(t[y].ch[0], val, x, t[y].ch[0]);
			pushup(y);
		}
	}
	return;
}
int Merge(int x, int y) {
	if(!x) return y; if(!y) return x;
	if(t[x].prio < t[y].prio) {
		int nw = ++poolcur; t[nw] = t[x];
		t[x].ch[1] = Merge(t[x].ch[1], y);
		pushup(x);
		return x;
	} else {
		int nw = ++poolcur; t[nw] = t[y];
		t[y].ch[0] = Merge(x, t[y].ch[0]);
		pushup(y);
		return y;
	}
}
void Insert(int &root, int val) {
	int x, y;
	Split(root, val, x, y);
	root = Merge(Merge(x, newnode(val)), y);
	return;
}
void Remove(int &root, int val) {
	int x, y, z;
	Split(root, val, x, z);
	Split(x, val - 1, x, y);
	y = Merge(t[y].ch[0], t[y].ch[1]);
	root = Merge(Merge(x, y), z);
	return;
}
int getrnk(int &root, int val) {
	int x, y;
	Split(root, val - 1, x, y);
	int ans = t[x].siz + 1;
	root = Merge(x, y);
	return ans;
}
int findkth(int cur, int k) {
	if(k <= t[lson].siz) return findkth(lson, k);
	if(k == t[lson].siz + 1) return t[cur].val;
	return findkth(rson, k - t[lson].siz - 1);
}
int getpre(int &root, int val) {
	int x, y;
	Split(root, val - 1, x, y);
	if(!x) return -inf;
	int k = t[x].siz;
	int ans = findkth(x, k);
	root = Merge(x, y);
	return ans;
}
int getnxt(int &root, int val) {
	int x, y;
	Split(root, val, x, y);
	if(!y) return inf;
	int ans = findkth(y, 1);
	root = Merge(x, y);
	return ans;
}

int main() {
	srand(time(NULL));
	n = rd();
	int ver, opt, x;
	for(int i = 1; i <= n; ++i) {
		ver = rd(); opt = rd(); x = rd();
		Root[i] = Root[ver];
		switch(opt) {
			case 1: Insert(Root[i], x); break;
			case 2: Remove(Root[i], x); break;
			case 3: printf("%d\n", getrnk(Root[i], x)); break;
			case 4: printf("%d\n", findkth(Root[i], x)); break;
			case 5: printf("%d\n", getpre(Root[i], x)); break;
			case 6: printf("%d\n", getnxt(Root[i], x)); break;
		}
	}
	return 0;
}

  


 

posted @ 2018-05-22 09:17  EvalonXing  阅读(339)  评论(0编辑  收藏  举报