[Data]treap

TREAP

treap(树堆)是指有一个随机附加值满足堆的性质的二叉搜索树,基本操作期望时间复杂度为O(logn),相比于其他平衡树,treap实现较简单,且能实现随机平衡。

在这里我就讲下小根堆的treap(大根堆一样),treap在SBT的性质上还附加了一个随机值(优先级),小根堆的话,当前节点的优先级一定小于其子树中的优先级;

 

像上面就是一棵(小根堆)treap;

插入操作:按造要插入的数的KEY值来决定它要往当前节点的右子树走还是左子树走,找到合适位置后再来考虑它的随机值,维护堆的性质,递归实现即可;

旋转操作:其实和SBT是一样的:当我们插入一个数,在找到它的位置过程中,它的随机值可能不满足堆的性质,若它的随机值小于当前节点,我们需根据它的位置来进行相应

的左旋或右旋;

删除操作:删除值为x的值,从根开始找,找到x值后,我们需把它旋到叶子节点才能进行删除,通过判断x值的左右子树节点的随机值旋转,若x.l.rd<x.r.rd,进行右旋,否则左旋;

这些就是基本的操作啦,求前驱后继就不用我讲了吧;

luogu 3369:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 using namespace std;
  5 
  6 struct TREAP{
  7     int l,r,val,sz,recy,rd;
  8 }t[1000000];
  9 
 10 int m,size,root,ans;
 11 
 12 void update(int k){
 13     t[k].sz=t[t[k].l].sz+t[t[k].r].sz+t[k].recy;
 14 }
 15 
 16 void left_rotate(int &k){
 17     int y=t[k].r;t[k].r=t[y].l;t[y].l=k;
 18     t[y].sz=t[k].sz;update(k);k=y;
 19 }
 20 void right_rotate(int &k){
 21     int y=t[k].l;t[k].l=t[y].r;t[y].r=k;
 22     t[y].sz=t[k].sz;update(k);k=y;
 23 }
 24 
 25 void insert(int &k,int x){
 26     if (k==0){
 27         ++size;k=size;t[k].sz=t[k].recy=1;
 28         t[k].val=x;t[k].rd=rand();return ;
 29     }
 30     ++t[k].sz;
 31     if (t[k].val==x) ++t[k].recy;
 32     else if (x>t[k].val){
 33         insert(t[k].r,x);
 34         if (t[t[k].r].rd<t[k].rd) left_rotate(k);
 35     }else{
 36         insert(t[k].l,x);
 37         if (t[t[k].l].rd<t[k].rd) right_rotate(k);
 38     }
 39 }
 40 
 41 void del(int &k,int x){
 42     if (k==0) return ;
 43     if (t[k].val==x){
 44         if (t[k].recy>1){
 45             --t[k].recy;--t[k].sz;return ;
 46         }
 47         if (t[k].l*t[k].r==0) k=t[k].l+t[k].r;
 48         else if (t[t[k].l].rd<t[t[k].r].rd) 
 49                     right_rotate(k),del(k,x);
 50                else left_rotate(k),del(k,x);
 51     }
 52     else if (x>t[k].val)
 53                 --t[k].sz,del(t[k].r,x);
 54            else --t[k].sz,del(t[k].l,x);
 55 }
 56 
 57 int atrank(int k,int x){
 58     if (k==0) return 0;
 59     if (t[k].val==x) return t[t[k].l].sz+1;
 60     else if (x>t[k].val)
 61             return t[t[k].l].sz+t[k].recy+atrank(t[k].r,x);
 62        else return atrank(t[k].l,x);
 63 }
 64 
 65 int rerank(int k,int x){
 66     if (k==0) return 0;
 67     if (x<=t[t[k].l].sz) return rerank(t[k].l,x);
 68     else if (x>t[t[k].l].sz+t[k].recy)
 69             return rerank(t[k].r,x-t[k].recy-t[t[k].l].sz);
 70        else return t[k].val;
 71 }
 72 
 73 void pred(int k,int x){
 74     if (k==0) return ;
 75     if (t[k].val<x){
 76         ans=k;pred(t[k].r,x);
 77     }else pred(t[k].l,x);
 78 }
 79 
 80 void succ(int k,int x){//找后缀 
 81     if (k==0) return ;
 82     if (t[k].val>x){
 83         ans=k;succ(t[k].l,x);
 84     }else succ(t[k].r,x);
 85 }
 86 
 87 int main(){
 88     int f,x;
 89     scanf("%d",&m);
 90     for (int i=1;i<=m;++i){
 91         scanf("%d%d",&f,&x);ans=0;
 92         if (f==1) insert(root,x);
 93        // printf("%d",root);
 94         if (f==2) del(root,x);
 95       //  printf("%d",root);
 96         if (f==3) printf("%d\n",atrank(root,x));
 97         if (f==4) printf("%d\n",rerank(root,x));
 98         if (f==5) {pred(root,x);printf("%d\n",t[ans].val);}
 99         if (f==6) {succ(root,x);printf("%d\n",t[ans].val);}
100     }
101     return 0;
102 }
View Code

 

posted @ 2018-01-01 14:48  Konnyaku  阅读(212)  评论(0)    收藏  举报