【模板】非旋转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 }
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 }
洛谷3369