Splay入门

这几天了解了一下平衡树,大概有如下几种:

AVL, 红黑, SBT, splay, treap, 后两者不是很严格的平衡。

反正先拿splay练手了,感觉比较热门。。。

平衡树的维护都靠旋转,splay也是。

其核心是Splay(x, goal)操作:把节点x一层层Rotate上去,直到x到达目的地goal下方;

它支持任意区间的更新,查询,插入,删除and翻转,O(lgn)。

模板来源:(盗用自notonlysuccess牛)

  http://www.notonlysuccess.com/index.php/splay-tree/

用法:(来自Crash牛)

  http://www.docin.com/p-62465596.html

习题一道:

Play with Chain
此题有splay的最独特的操作 区间插入,删除and翻转

贴个膜板:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string>
  4 #include <algorithm>
  5 #include <string.h>
  6 #include <stdlib.h>
  7 #define MAXN 300500
  8 #define INF 0x3f3f3f3f
  9 #define keyTree  ch[ ch[root][1] ][0]
 10 using namespace std;
 11 
 12 int num[MAXN], id;
 13 
 14 struct SplayTree{
 15     int sz[MAXN];        //size
 16     int ch[MAXN][2];     //child
 17     int pre[MAXN];        //father 
 18     int root, top1, top2;
 19     int ss[MAXN], que[MAXN];
 20     
 21     inline void Rotate(int x, int r){    //r:(0,左);(1,右) 
 22         int y = pre[x];
 23         pushDown(y);    
 24         pushDown(x);    
 25         ch[y][!r] = ch[x][r];
 26         if(ch[x][r]) pre[ ch[x][r] ] = y;
 27         pre[x] = pre[y];
 28         if(pre[y]) ch[ pre[y] ][ ch[pre[y]][1]==y ] = x;
 29         ch[x][r] = y;
 30         pre[y] = x;
 31         pushUp(y);
 32     }
 33     
 34     inline void Splay(int x, int goal){
 35         pushDown(x);
 36         while(pre[x] != goal){
 37             if(pre[pre[x]] == goal)
 38                 Rotate(x, ch[pre[x]][0] == x);    //左儿则右旋 
 39             else{
 40                 int y = pre[x], z = pre[y];
 41                 int r = (ch[z][0] == y);
 42                 if(ch[y][r]==x)
 43                     Rotate(x, !r), Rotate(x, r);    //Rx, Rx
 44                 else
 45                     Rotate(y, r), Rotate(x, r);    //Ry, Rx 
 46             }
 47         }
 48         pushUp(x);
 49         if(goal == 0)    root = x;         
 50     }
 51     
 52     //把第k位的数转到goal下边
 53     inline void RotateTo(int k, int goal){
 54         int x = root;
 55         pushDown(x);
 56         while(sz[ ch[x][0] ] != k){
 57             if(k < sz[ ch[x][0] ] ) x = ch[x][0];
 58             else{
 59                 k -= (sz[ ch[x][0] ]+1);
 60                 x = ch[x][1];
 61             }
 62             pushDown(x);
 63         }//找到 第k位的数;
 64         Splay(x, goal); 
 65     }
 66     
 67     //把以x为祖先结点删掉放进内存池,回收内存
 68     //bfs(子树x);
 69     inline void erase(int x){
 70         int head = 0, tail = 0;
 71         for(que[tail++]=x; head<tail; head++){
 72             ss[top2++] = que[head];
 73             if(ch[ que[head] ][0])    que[tail++] = ch[ que[head] ][0];
 74             if(ch[ que[head] ][1])    que[tail++] = ch[ que[head] ][1];
 75         }
 76     }
 77 
 78     //-------------以上一般不修改-------------------
 79     void debug( ) { printf("%d
",root); Treaval(root); }
 80     void Treaval( int x )
 81     {
 82         if( x )
 83         {
 84             Treaval( ch[x][0] );
 85             printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d
",
 86                     x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
 87             Treaval( ch[x][1] );
 88         }
 89     }
 90     //以上Debug
 91     
 92     //以下是题目的特定函数:
 93     inline void NewNode( int &x, int c ){
 94         if( top2 ) x = ss[--top2];//用栈手动压的内存池
 95         else x = ++top1;
 96         ch[x][0] = ch[x][1] = pre[x] = 0;
 97         sz[x] = 1, val[x] = c, rev[x] = 0;
 98     }
 99     
100     inline void pushDown(int x){
101         if(rev[x]){
102             if(ch[x][0]) rev[ch[x][0]] ^=1;
103             if(ch[x][1]) rev[ch[x][1]] ^=1;
104             swap(ch[x][0], ch[x][1]);
105             rev[x] = 0;
106         }
107     }
108     
109     inline void pushUp( int x ) {
110         sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ];
111     }
112     
113     inline void makeTree( int &x, int l, int r, int f ){
114         if( l > r ) return ;
115         int m = ( l + r ) >> 1;
116         NewNode( x, num[m] );        
117         makeTree( ch[x][0], l, m - 1, x );
118         makeTree( ch[x][1], m + 1, r, x );
119         pre[x] = f;
120         pushUp(x);
121     }
122     
123     inline void init( int n ){
124         ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
125         rev[0] = 0, root = top1 = 0;
126         //为了方便处理边界,加两个边界顶点!!        
127         NewNode( root , -1 );
128         NewNode( ch[root][1], -1 );
129         pre[ ch[root][1] ] = root;        
130 
131         for( int i = 0; i < n; i++ ) 
132             num[i] = i+1;
133         makeTree( keyTree, 0, n - 1, ch[root][1] );
134         pushUp( ch[root][1] );
135         pushUp( root );
136     }
137     
138     inline int del(int l, int r){
139         RotateTo(l-1, 0);
140         RotateTo(r+1, root);
141         int ans = keyTree;
142         keyTree = 0;
143         pushUp( ch[root][1] );
144         pushUp( root );
145         return ans;
146     }
147     
148     inline void ins(int d, int s){
149         RotateTo(d, 0);
150         RotateTo(d+1, root);
151         keyTree = s, pre[s] = ch[root][1];
152         pushUp( ch[root][1] );
153         pushUp( root );
154     }
155     
156     inline void flip(int l, int r){
157         RotateTo(l-1, 0);
158         RotateTo(r+1, root);
159         rev[keyTree] ^= 1;
160     }
161     
162     inline void print(int p){
163         if(!p)    return ;
164         pushDown(p);
165         print(ch[p][0]);
166         num[id++] = val[p];
167         print(ch[p][1]);
168     }
169     
170     int val[MAXN];
171     int rev[MAXN];
172 }spt;
173 
174 int main( ) {
175     int n, m;
176     while(scanf("%d%d",&n,&m) && n>0 && m>0){
177         spt.init( n );
178         while( m-- ){
179             int a, b, c;
180             char op[2];
181             scanf("%s%d%d", op, &a, &b);
182             if( op[0] == 'C' ){
183                 scanf("%d", &c);
184                 int s = spt.del(a, b);
185                 spt.ins(c, s);
186             }                
187             else
188                 spt.flip(a, b);
189         }
190         id = 0;
191         spt.print(spt.root);
192         for(int i=1; i<=n; i++)
193             printf("%d%c", num[i], i!=n? ' ': '
');
194     }
195     return 0;
196 }
View Code
原文地址:https://www.cnblogs.com/KimKyeYu/p/3533057.html