<范浩强treap>-函数式平衡树
范好强treap是一种毒瘤treap,它并不用通过旋转来达到平衡,它主要有两种操作:
merge(x,y):将x的子树和y的子树合并起来;{注意:merge操作中,x子树中的最大值永远会小于等于y子树中的最小值
所以在merge的过程中只需要考虑随机值,而不需考虑key值}所以merge时要不就x连接在y的左儿子,
要不就y连接在x的右儿子,这时就需通过随机值来确定哪个为儿子。

1 int merge(int x,int y){ 2 //printf("merge:%d %d ",x,y); 3 if(!x||!y) return x+y; 4 else{ 5 if(t[x].fix<t[y].fix){ 6 int r=copynode(x); 7 t[r].son[1]=merge(t[r].son[1],y); 8 update(r); 9 return r; 10 } 11 else{ 12 int r=copynode(y); 13 t[r].son[0]=merge(x,t[r].son[0]); 14 update(r); 15 return r; 16 } 17 } 18 }
split(k,x,y):将小于等于k值的数分离到以x为根的子树中,另外一部分分离到y;只需判断当前节点与k的关系,
若小于等于K,则它的左儿子就一定小于k,但右儿子就不一定了;若大于K,则它的右儿子就一定大于k,左儿子就不一定了。

1 void split(int now,int k,int &x,int &y){ 2 //printf("split:%d %d ",x,y); 3 if(!now) x=y=0; 4 else{ 5 if(t[now].key<=k){ 6 x=copynode(now); 7 split(t[x].son[1],k,t[x].son[1],y); 8 } 9 else{ 10 y=copynode(now); 11 split(t[y].son[0],k,x,t[y].son[0]); 12 } 13 update(x); 14 update(y); 15 } 16 }
以下的操作均是通过merge和split实现的:
《insert》——插入
设插入的值为k,只需要把当前的树split(k,x,y),k单独一棵树,然后再merge(k,x),最后merge(merge(k,x),y);

1 void insert(int bb,int val){ 2 int x,y,z; 3 x=y=z=0; 4 split(root[bb],val,x,y); 5 z=newnode(val); 6 root[bb]=merge(merge(x,z),y); 7 }
《delet》——删除
只需要先把树分成大于删除值与小于等于删除值两部分z,x,再在x中分离出小于删除值与等于删除值的树x,y,在y子树中,由于我们只要删除一个数,
所以只需删除y中的根节点,再把y的左右儿子合并起来。

1 void del(int bb,int val){ 2 int x=0,y=0,z=0; 3 split(root[bb],val,x,z); 4 split(x,val-1,x,y); 5 y=merge(t[y].son[0],t[y].son[1]); 6 root[bb]=merge(merge(x,y),z); 7 }
求第k值的排名(比它小的数+1)——getkth
分离出小于k的数存在树x中,然后排名等于x的子树+1。

1 int getkth(int bb,int val){ 2 int x,y,ret; 3 split(root[bb],val-1,x,y); 4 ret=t[x].sz+1; 5 return ret; 6 }
求排名为k的数——getval
用一个while循环即可获得排名为k的值emm 。

1 int getpos(int now,int k){ 2 while(1){ 3 if(k<=t[t[now].son[0]].sz) now=t[now].son[0]; 4 else if(k==t[t[now].son[0]].sz+1) {return now;} 5 else{ 6 k-=t[t[now].son[0]].sz+1; 7 now=t[now].son[1]; 8 } 9 } 10 } 11 int getval(int now,int k){ 12 int x; 13 x=getpos(now,k); 14 //printf("pos:%d ",x); 15 return t[x].key; 16 }
求val前驱——getpre
先split(val-1,x,y),然后转换为求排名为k(sz[x])的数即可。

1 int getpre(int bb,int val){ 2 int x,y,k,ret; 3 split(root[bb],val-1,x,y); 4 if(x) k=t[x].sz; 5 else return -2147483647; 6 ret=getval(x,k); 7 return ret; 8 }
求val后继——getsuc
原理与求pre一样吧嗯嗯。

1 int getsuc(int bb,int val){ 2 int x,y,ret; 3 split(root[bb],val,x,y); 4 if(!y) return 2147483647; 5 ret=getval(y,1); 6 return ret; 7 }
luogu 3835:

1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define maxn 500009 5 using namespace std; 6 struct node{ 7 int son[2]; 8 int fix,key,sz; 9 }t[maxn*50]; 10 int root[maxn],cnt=1; 11 int copynode(int x){ 12 cnt++; 13 t[cnt]=t[x]; 14 return cnt; 15 } 16 void update(int cur){ 17 if(cur)t[cur].sz=t[t[cur].son[0]].sz+t[t[cur].son[1]].sz+1; 18 } 19 int newnode(int val){ 20 cnt++; 21 t[cnt].son[0]=t[cnt].son[1]=0; 22 t[cnt].key=val; 23 t[cnt].sz=1; 24 t[cnt].fix=rand(); 25 return cnt; 26 } 27 void split(int now,int k,int &x,int &y){ 28 //printf("split:%d %d ",x,y); 29 if(!now) x=y=0; 30 else{ 31 if(t[now].key<=k){ 32 x=copynode(now); 33 split(t[x].son[1],k,t[x].son[1],y); 34 } 35 else{ 36 y=copynode(now); 37 split(t[y].son[0],k,x,t[y].son[0]); 38 } 39 update(x); 40 update(y); 41 } 42 } 43 int merge(int x,int y){ 44 //printf("merge:%d %d ",x,y); 45 if(!x||!y) return x+y; 46 else{ 47 if(t[x].fix<t[y].fix){ 48 int r=copynode(x); 49 t[r].son[1]=merge(t[r].son[1],y); 50 update(r); 51 return r; 52 } 53 else{ 54 int r=copynode(y); 55 t[r].son[0]=merge(x,t[r].son[0]); 56 update(r); 57 return r; 58 } 59 } 60 } 61 void insert(int bb,int val){ 62 int x,y,z; 63 x=y=z=0; 64 split(root[bb],val,x,y); 65 z=newnode(val); 66 root[bb]=merge(merge(x,z),y); 67 } 68 void del(int bb,int val){ 69 int x=0,y=0,z=0; 70 split(root[bb],val,x,z); 71 split(x,val-1,x,y); 72 y=merge(t[y].son[0],t[y].son[1]); 73 root[bb]=merge(merge(x,y),z); 74 } 75 int getkth(int bb,int val){ 76 int x,y,ret; 77 split(root[bb],val-1,x,y); 78 ret=t[x].sz+1; 79 return ret; 80 } 81 int getpos(int now,int k){ 82 while(1){ 83 if(k<=t[t[now].son[0]].sz) now=t[now].son[0]; 84 else if(k==t[t[now].son[0]].sz+1) {return now;} 85 else{ 86 k-=t[t[now].son[0]].sz+1; 87 now=t[now].son[1]; 88 } 89 } 90 } 91 int getval(int now,int k){ 92 int x; 93 x=getpos(now,k); 94 //printf("pos:%d ",x); 95 return t[x].key; 96 } 97 int getpre(int bb,int val){ 98 int x,y,k,ret; 99 split(root[bb],val-1,x,y); 100 if(x) k=t[x].sz; 101 else return -2147483647; 102 ret=getval(x,k); 103 return ret; 104 } 105 int getsuc(int bb,int val){ 106 int x,y,ret; 107 split(root[bb],val,x,y); 108 if(!y) return 2147483647; 109 ret=getval(y,1); 110 return ret; 111 } 112 int main() 113 { 114 int n,bb,opt,val; 115 scanf("%d",&n); 116 for(int i=1;i<=n;i++){ 117 scanf("%d%d%d",&bb,&opt,&val); 118 root[i]=root[bb]; 119 switch(opt){ 120 case 1:insert(i,val);break; 121 case 2:del(i,val); break; 122 case 3:printf("%d ",getkth(i,val));break; 123 case 4:printf("%d ",getval(root[i],val));break; 124 case 5:printf("%d ",getpre(i,val));break; 125 case 6:printf("%d ",getsuc(i,val));break; 126 } 127 } 128 return 0; 129 }