【模板】非旋转Treap

Treap,也叫做树堆,是指有一个随机附加域满足堆的性质的二叉搜索树。

如果一棵二叉搜索树插入节点的顺序是随机的,那我们得到的二叉搜索树在大多数情况下是平衡的,期望高度是log(n).

但有些情况下我们并不能得知所有待插入节点,打乱以后再插入,这时我们需要给二叉搜索树加上一个随机附加域,并使这个随机附加域(优先级)满足堆的性质,以此来实现“乱序插入”的想法,使二叉搜索树保持平衡。

Treap可以满足的序列操作:

1,插入一个数x

2,删除一个数x

3,查询x的排名

4,查询排名为x的数

5,查询x的前驱

6,查询x的后继

Treap的基本操作

1,newnode新建节点

2,split分裂 把Treap按照权值分割为两部分

3,merge合并 把Treap的两部分进行合并

4,insert插入 把Treap按照插入的权值Val分裂为两部分,然后merge左边和新点,再merge新的左边和右边

5,delete删除 把Treap分裂两次,中间那部分不管它,把两边merge一下

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define ls (a[u].l)
 4 #define rs (a[u].r)
 5 using namespace std;
 6 const int maxn=200010;
 7 int n,k,x,y,z,v,tot,root;
 8 struct treap{int l,r,v,rnd,size;}a[maxn];
 9 inline void read(int &k){
10     k=0; int f=1; char c=getchar();
11     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
12     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
13     k*=f;
14 }
15 void newnode(int v){a[++tot]=(treap){0,0,v,rand()+1,1};}
16 void update(int u){a[u].size=a[ls].size+a[rs].size+1;}
17 void split(int u,int k,int &x,int &y){
18     if(!k){x=0; y=u; return;}
19     if(a[u].size==k){x=u; y=0; return;}
20     if(a[ls].size>=k) split(ls,k,x,ls),y=u;
21     else split(rs,k-a[ls].size-1,rs,y),x=u;
22     update(u);
23 }
24 int merge(int x,int y){
25     if(!(x*y)) return x+y;
26     if(a[x].rnd>a[y].rnd){
27         a[y].l=merge(x,a[y].l); update(y); return y;
28     }
29     else{
30         a[x].r=merge(a[x].r,y); update(x); return x;
31     }
32 }
33 int qrank(int u,int val){
34     if(!u) return 0;
35     if(a[u].v>=val) return qrank(ls,val);
36     return qrank(rs,val)+a[ls].size+1;
37 }
38 int qval(int u,int k){
39     if(a[ls].size+1==k) return a[u].v;
40     return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-1);
41 }
42 int main(){
43     srand(20020705); root=tot=1; a[root].v=2e9; a[root].size=1;
44     read(n);
45     while(n--){
46         read(k); read(v);
47         if(k==1){//插入 
48             split(root,qrank(root,v),x,y);
49             newnode(v); root=merge(merge(x,tot),y);
50         }
51         if(k==2){//删除 
52             split(root,qrank(root,v),x,y);
53             split(y,1,z,y); root=merge(x,y);
54         }
55         if(k==3) printf("%d\n",qrank(root,v)+1);//查询x的排名 
56         if(k==4) printf("%d\n",qval(root,v));//查询排名为x的数 
57         if(k==5) printf("%d\n",qval(root,qrank(root,v)));//查询x的前驱 
58         if(k==6) printf("%d\n",qval(root,qrank(root,v+1)+1));//查询x的后继 
59     }
60     return 0;
61 }
View Code
 1 #include<cstdio>
 2 #include<algorithm>
 3 #define ls (a[u].l)
 4 #define rs (a[u].r)
 5 using namespace std;
 6 const int maxn=200010;
 7 int n,k,x,y,z,v,tot,root;
 8 struct treap{int l,r,v,rnd,size;}a[maxn];
 9 inline int read(){
10     int k=0,f=1; char c=getchar();
11     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
12     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
13     return k*f;
14 }
15 void newnode(int val){a[++tot]=(treap){0,0,val,rand()+1,1};}
16 void update(int u){a[u].size=a[ls].size+a[rs].size+1;}
17 void split(int u,int k,int &x,int &y){
18     if(!k){x=0; y=u; return;}
19     if(a[u].size==k){x=u; y=0; return;}
20     if(a[ls].size>=k) split(ls,k,x,ls),y=u;
21     else split(rs,k-a[ls].size-1,rs,y),x=u;
22     update(u);
23 }
24 int merge(int x,int y){
25     if(!x||!y) return x+y;
26     if(a[x].rnd<a[y].rnd){a[x].r=merge(a[x].r,y); update(x); return x;}
27     else{a[y].l=merge(x,a[y].l); update(y); return y;}
28 }
29 int qrank(int u,int val){
30     if(!u) return 0;
31     return a[u].v>=val?qrank(ls,val):qrank(rs,val)+a[ls].size+1;
32 }
33 int qval(int u,int k){
34     if(a[ls].size+1==k) return a[u].v;
35     return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-1);
36 }
37 int main(){
38     srand(20020705); a[root=tot=1]=(treap){0,0,2e9,0,1};
39     n=read();
40     while(n--){
41         k=read(); v=read();
42         if(k==1){
43             split(root,qrank(root,v),x,y);
44             newnode(v); root=merge(merge(x,tot),y);
45         }
46         if(k==2){
47             split(root,qrank(root,v),x,y); split(y,1,z,y);
48             root=merge(x,y);
49         }
50         if(k==3) printf("%d\n",qrank(root,v)+1);
51         if(k==4) printf("%d\n",qval(root,v));
52         if(k==5) printf("%d\n",qval(root,qrank(root,v)));
53         if(k==6) printf("%d\n",qval(root,qrank(root,v+1)+1)); 
54     }
55     return 0;
56 }
View Code

洛谷3369

posted @ 2017-11-27 20:21  Driver_Lao  阅读(227)  评论(0编辑  收藏  举报