zoukankan      html  css  js  c++  java
  • 用 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
    ", getrnk(Root[i], x)); break;
    			case 4: printf("%d
    ", findkth(Root[i], x)); break;
    			case 5: printf("%d
    ", getpre(Root[i], x)); break;
    			case 6: printf("%d
    ", getnxt(Root[i], x)); break;
    		}
    	}
    	return 0;
    }
    

      


    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    应当将指针变量用“==”或“!=”与 NULL 比较
    不可将浮点变量用“==”或“!=”与任何数字比较
    应当将整型变量用“==”或“!=”直接与 0 比较
    不可将布尔变量直接与 TRUE、FALSE 或者 1、0 进行比较
    不要把程序中的复合表达式与“真正的数学表达式”混淆
    不要有多用途的复合表达式
    不要编写太复杂的复合表达式
    用括号确定表达式的操作顺序
    为了防止某一软件库中的一些标识符和其它软件库中的冲突
    类的数据成员加前缀 m_(表示 member)
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9070393.html
Copyright © 2011-2022 走看看