加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

几种常用平衡树的概述(持续更新]

发布时间:2020-12-14 04:27:59 所属栏目:大数据 来源:网络整理
导读:1. Treap Treap是一种基于旋转来维护平衡的平衡树,它通过给每个节点赋一个随机值,并按照该值维护大(或)根堆,以此实现平衡;也因此,它叫Treap ( Binaty Search Tree + heap ) 核心操作 : 左旋和右旋 ? 左旋 : 对节点x进行左旋操作,即把x的右子节点旋到

1. Treap

  Treap是一种基于旋转来维护平衡的平衡树,它通过给每个节点赋一个随机值,并按照该值维护大(或)根堆,以此实现平衡;也因此,它叫Treap ( Binaty Search Tree + heap )

  核心操作 : 左旋和右旋

       ? 左旋 : 对节点x进行左旋操作,即把x的右子节点旋到左边,具体操作就是把右子树的左子节点连到x,x的右子节点连在x和x的父亲之间;

       ? 右旋 : 旋左;

  代码如下 :

  1 //Author : 15owzLy1
  2 //luogu3369.cpp
  3 //2018 12 05      22:37:51
  4 #include <iostream>
  5 #include <cstdio>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <cstdlib>
  9 #define INF 2100000000
 10 typedef long long ll;
 11 typedef double db;
 12 template<typename T>inline void read(T &_) {
 13     _=0;int __=0;char ___=getchar();
 14     while(___<0||___>9)__|=(___==-),___=getchar();
 15     while(___>=0&&___<=9)_=(_<<1)+(_<<3)+(___^48),___=getchar();
 16     _=__?-_:_;
 17 }
 18 
 19 const int N = 100005;
 20 int q,opt,y,res;
 21 
 22 class Treap {
 23 #define t a[p]
 24 #define lson a[a[p].l]
 25 #define rson a[a[p].r]
 26 private :
 27     int tot; 
 28     struct node {
 29         int l,r,val,num,w,size;
 30     }a[N];
 31     inline void push_up(int p) {
 32         t.size=lson.size+rson.size+t.val;
 33     }
 34     inline void zig(int &p) {
 35         int ts=lson.r,tmp=t.l;
 36         lson.size=t.size;
 37         lson.r=p,t.l=ts;
 38         push_up(p);
 39         p=tmp;
 40     }
 41     inline void zag(int &p) {
 42         int ts=rson.l,tmp=t.r;
 43         rson.size=t.size;
 44         rson.l=p,t.r=ts;
 45         push_up(p);
 46         p=tmp;
 47     }
 48     inline void new_node(int &p,int x) {
 49         t=(node){0,0,1,x,rand(),1};
 50     }
 51 public :
 52     int rt;
 53     void debug(int p) {
 54         if(t.l) debug(t.l);
 55         printf("num : %d  p : %dn",t.num,p);
 56         if(t.r) debug(t.r);
 57     }
 58     void insert(int &p,int x) {
 59         if(!p) { p=++tot; new_node(p,x); return ; }
 60         ++t.size;
 61         if(t.num==x) ++t.val;
 62         else if(x<t.num) {
 63             insert(t.l,x);
 64             if(t.w<lson.w) zig(p);
 65         }
 66         else {
 67             insert(t.r,x);
 68             if(t.w<rson.w) zag(p);
 69         }
 70     }
 71     void del(int &p,int x) {
 72         if(t.num==x) {
 73             if(t.val>1) --t.val,--t.size;
 74             else if(t.l==0||t.r==0) p=t.l?t.l:t.r;
 75             else if(lson.w>rson.w) zig(p),del(p,x);
 76             else                   zag(p),x);
 77         }
 78         else if(x<t.num) { --t.size; del(t.l,x); }
 79         else             { --t.size; del(t.r,x); }
 80     }
 81     int query_rank(int p,int x) {
 82         if(x==t.num)     return lson.size+1;
 83         else if(x<t.num) return query_rank(t.l,x);
 84         else             return query_rank(t.r,x)+lson.size+t.val;
 85     }
 86     int query_num(int p,int x) {
 87         if(!p) return 0;
 88         if(lson.size<x&&lson.size+t.val>=x) return t.num;
 89         if(lson.size>=x) return query_num(t.l,x);
 90         return query_num(t.r,x-t.val-lson.size);
 91     }
 92     void query_pre(int p,int x) {
 93         if(!p) return ;
 94         if(x<=t.num) query_pre(t.l,x);
 95         else {
 96             res=t.num;
 97             query_pre(t.r,x);
 98         }
 99     }
100     void query_sub(int p,int x) {
101         if(!p) return ;
102         if(x>=t.num) query_sub(t.r,x);
103         else {
104             res=t.num;
105             query_sub(t.l,x);
106         }
107     }
108 }T;
109 
110 int main() {
111 #ifndef ONLINE_JUDGE
112     freopen("luogu3369.in","r",stdin);
113     freopen("luogu3369.out","w",stdout);
114 #endif
115     srand(20030215);
116     read(q);
117     while(q--) {
118         read(opt),read(y);
119         if(opt==1)        T.insert(T.rt,y);
120         else if(opt==2) T.del(T.rt,y);
121         else if(opt==3) printf("%dn",T.query_rank(T.rt,y));
122         else if(opt==4) printf("%dn",T.query_num(T.rt,y));
123         else if(opt==5) {
124             res=-INF;
125             T.query_pre(T.rt,y);
126             printf("%dn",res);
127         }
128         else {
129             res=INF;
130             T.query_sub(T.rt,y);
131             printf("%dn",res);
132         }
133     }
134     return 0;
135 }
View Code

2. Splay

  Splay是一种基于旋转来维护平衡的平衡树,它通过旋转操作破坏当前存在的链维护相对平衡;

  核心操作 : Splay ,rotate

       ? Splay : 把x旋到根。如果是一个“之”字形,就旋两次x;如果是一条直链,就旋fa[x],再旋x;

       ? rotate : 旋转操作;

  Splay支持区间操作,如:区间翻转;

  代码如下:

 1 //Author : 15owzLy1
 2 //luogu3391.cpp
 3 //2018 12 11      10:38:52
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #define INF 2100000000
 8 typedef long long ll;
 9 typedef double db;
10 template<typename T>inline void read(T &_) {
11     _=0;int __=0;char ___=getchar();
12     while(___<0||___>9)__|=(___==-),___=getchar();
13     while(___>=0&&___<=9)_=(_<<1)+(_<<3)+(___^48),___=getchar();
14     _=__?-_:_;
15 }
16 
17 const int N = (int)1e5+5;
18 int n,q,y;
19 
20 class Splay {
21 #define lson c[p][0]
22 #define rson c[p][1]
23 private :
24     int c[N][2],fa[N],size[N],num[N],lazy[N];
25     inline void push_up(int p) {
26         size[p]=size[lson]+size[rson]+1;
27     }
28     inline void push_down(int p) {
29         if(lazy[p]) {
30             std::swap(lson,rson);
31             lazy[lson]^=1,lazy[rson]^=1;
32             lazy[p]=0;
33         }
34     }
35     inline void rotate(int x,int &p) {
36         int y=fa[x],z=fa[y],l,r;
37         l=(c[y][1]==x); r=l^1;
38         if(y==p) p=x;
39         else     c[z][c[z][1]==y]=x;
40         fa[c[x][r]]=y,fa[x]=z,fa[y]=x;    
41         c[y][l]=c[x][r],c[x][r]=y;
42         push_up(x),push_up(y);
43     }
44 public :
45     int rt;
46     inline void splay(int x,int &p) {
47         while(x!=p) {
48             int y=fa[x],z=fa[y];
49             if(y!=p) {
50                 if(c[y][0]==x^c[z][0]==y) rotate(x,p);
51                 else rotate(y,p);
52             }
53             rotate(x,p);
54         }
55     }
56     int find(int p,int rank) {
57         push_down(p);
58         if(size[lson]+1==rank)   return p;
59         else if(size[lson]>=rank)return find(lson,rank);
60         else                  return find(rson,rank-size[lson]-1);
61     }
62     inline void reverse(int x,int y) {
63         int l=find(rt,x),r=find(rt,y+2);
64         splay(l,rt),splay(r,c[l][1]);
65         lazy[c[r][0]]^=1;
66     }
67     void build(int l,int r,int father) {
68         if(l>r) return ;
69         int mid=l+r>>1;
70         c[father][mid>=father]=mid;
71         fa[mid]=father; size[mid]=1;
72         if(l==r) return ;
73         build(l,mid-1,mid);
74         build(mid+1,mid);
75         push_up(mid);
76     }
77 }T;
78 
79 int main() {
80 #ifndef ONLINE_JUDGE
81     freopen("luogu3391.in",stdin);
82 #endif
83     read(n),read(q);
84     T.rt=(n+3)>>1; T.build(1,n+2,T.rt);
85     while(q--) {
86         read(x),read(y);
87         T.reverse(x,y);
88     }
89     for(int i=2;i<=n+1;i++)
90         printf("%d ",T.find(T.rt,i)-1);
91     return 0;
92 }
View Code

3. FHQ Treap ( Persistence Treap)

  非旋Treap;

  核心操作:split,merge

      ? ?split:把当前的Treap分成两棵树,一棵上所有的节点大小<=k,另一棵>k;(递归实现

       merge :把两棵Treap合并,此时节点的大小已经满足平衡树定义,所以需要和Treap一样维护堆;

       通过split和merge,基本所有操作都可以暴力搞出来;

  代码如下 :

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cstdlib>
  5 
  6 template<typename T>inline void read(T &x) {
  7     x=0;int f=0;char c=getchar();
  8     while(c<0||c>9)f|=(c==-),c=getchar();
  9     while(c>=0&&c<=9)x=(x<<1)+(x<<3)+(c^48),c=getchar();
 10     x=f?-x:x;
 11 }
 12 
 13 const int N = (int)1e5+5;
 14 int q,n;
 15 
 16 class Persistence_Treap {
 17 #define t a[p]
 18 #define lson a[a[p].l]
 19 #define rson a[a[p].r]
 20 private :
 21     struct node {
 22         int l,size,w;
 23     }a[N];
 24     inline void push_up(int p) {
 25         t.size=lson.size+rson.size+1;
 26     }
 27     void split(int p,int &x,int &y,int k) {
 28         if(p==0) { x=y=0; return ; }
 29         if(t.num<=k) x=p,split(t.r,t.r,k);
 30         else         y=p,split(t.l,t.l,k);
 31         push_up(p);
 32     }
 33     int merge(int &p,int x,int y) {
 34         if(x==0||y==0) { p=x?x:y; return p; }
 35         if(a[x].w<a[y].w) { p=x; merge(t.r,y); }
 36         else              { p=y; merge(t.l,t.l); }
 37         push_up(p);
 38         return p;
 39     }
 40     inline int new_node(int k) {
 41         a[++tot]=(node){0,k,1,rand()};
 42         return tot;
 43     }
 44 public :
 45     int rt,tot;
 46     void debug(int p) {
 47         if(t.l) debug(t.l);
 48         printf("   %d %d %d %dn",lson.num,rson.num,t.size);
 49         if(t.r) debug(t.r);
 50     }
 51     inline void insert(int k) {
 52         int x=0,y=0,z=new_node(k);
 53         split(rt,k);
 54         merge(rt,merge(x,z),y);
 55     }
 56     inline void remove(int k) {
 57         int x=0,z=0;
 58         split(rt,k);
 59         split(x,z,k-1);
 60         merge(rt,merge(z,a[z].l,a[z].r)),y);
 61     }
 62     inline int find(int k) {
 63         int x=0,y=0,ret;
 64         split(rt,k-1);
 65         ret=a[x].size+1;
 66         merge(rt,y);
 67         return ret;
 68     }
 69     inline int kth(int p,int k) {
 70         while(lson.size+1!=k) {
 71             if(lson.size>=k) p=t.l;
 72             else             k-=lson.size+1,p=t.r;
 73         }
 74         return t.num;
 75     }
 76     inline int query_pre(int k) {
 77         int x=0,ret;
 78         split(rt,k-1);
 79         ret=kth(x,a[x].size);
 80         merge(rt,y);
 81         return ret;
 82     }
 83     inline int query_sub(int k) {
 84         int x=0,ret;
 85         split(rt,k);
 86         ret=kth(y,1);
 87         merge(rt,y);
 88         return ret;
 89     }
 90 }T;
 91 
 92 int main() {
 93 #ifndef ONLINE_JUDGE
 94     freopen("fhq_treap.in",stdin);
 95 #endif
 96     srand(20030215);
 97     read(q);
 98     while(q--) {
 99         read(opt),read(n);
100         switch(opt) {
101             case 1 : T.insert(n);break;
102             case 2 : T.remove(n);break;
103             case 3 : printf("%dn",T.find(n));break;
104             case 4 : printf("%dn",T.kth(T.rt,n));break;
105             case 5 : printf("%dn",T.query_pre(n));break;
106             case 6 : printf("%dn",T.query_sub(n));break;
107         }
108     }
109     return 0;
110 }
View Code

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读