[Data]FHQ treap

<范浩强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 }
merge

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

以下的操作均是通过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 }
insert

《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 }
delet

求第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 }
getkth

求排名为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 }
getval

求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 }
getpre

求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 }
getsuc

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 }        
FHQ treap
原文地址:https://www.cnblogs.com/Fish-/p/8178731.html