模板非旋转Treap

Posted Driver_Lao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板非旋转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 #include<ctime>
 4 #define ls (a[u].l)
 5 #define rs (a[u].r)
 6 using namespace std;
 7 const int maxn=200010;
 8 int n,k,x,y,z,v,tot,root;
 9 struct treap{int l,r,v,rnd,size;}a[maxn];
10 void read(int &k){
11     k=0; int f=1; char c=getchar();
12     while(c<0||c>9)c==-&&(f=-1),c=getchar();
13     while(0<=c&&c<=9)k=k*10+c-0,c=getchar();
14     k*=f;
15 }
16 void newnode(int v){a[++tot]=(treap){0,0,v,rand()+1,1};}
17 void update(int u){a[u].size=a[ls].size+a[rs].size+1;}
18 void split(int u,int k,int &x,int &y){
19     if(!k){x=0; y=u; return;}
20     if(a[u].size==k){x=u; y=0; return;}
21     if(a[ls].size>=k)split(a[u].l,k,x,a[u].l),y=u;
22     else split(a[u].r,k-a[ls].size-1,a[u].r,y),x=u;
23     update(u);
24 }
25 int merge(int x,int y){
26     if(!(x*y)) return x+y;
27     if(a[x].rnd>a[y].rnd){
28         a[y].l=merge(x,a[y].l); update(y); return y;
29     }
30     else{
31         a[x].r=merge(a[x].r,y); update(x); return x;
32     }
33 }
34 int qrank(int u,int val){
35     if(!u) return 0;
36     if(a[u].v>=val) return qrank(ls,val);
37     return qrank(rs,val)+a[ls].size+1;
38 }
39 int qval(int u,int k){
40     if(a[ls].size+1==k) return a[u].v;
41     return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-1);
42 }
43 int main(){
44     srand(time(0)); root=tot=1; a[root].v=2e9; a[root].size=1;
45     read(n); 
46     while(n--){
47         read(k); read(v);
48         if(k==1){//插入 
49             split(root,qrank(root,v),x,y);
50             newnode(v); root=merge(merge(x,tot),y);
51         }
52         if(k==2){//查询 
53             split(root,qrank(root,v),x,y);
54             split(y,1,z,y); root=merge(x,y);
55         }
56         if(k==3) printf("%d\n",qrank(root,v)+1);//查询x的排名 
57         if(k==4) printf("%d\n",qval(root,v));//查排名为x的数 
58         if(k==5) printf("%d\n",qval(root,qrank(root,v)));//求x的前驱 
59         if(k==6) printf("%d\n",qval(root,qrank(root,v+1)+1));//求x的后继 
60     }
61     return 0;
62 }
63                     
View Code

 

洛谷3369

以上是关于模板非旋转Treap的主要内容,如果未能解决你的问题,请参考以下文章

模板fhq-treap

平衡树讲解(旋转treap,非旋转treap,splay)

[bzoj1861][Zjoi2006]Book 书架_非旋转Treap

非旋转Treap详解

可持久化Treap(fhq Treap,非旋转式Treap)学习(未完待续)

[bzoj1895][Pku3580]supermemo_非旋转Treap