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\n",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\n", 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? ' ': '\n'); 194 } 195 return 0; 196 }