• 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
  • 相关阅读:
    BZOJ 1046: [HAOI2007]上升序列(LIS)
    BZOJ 1001: [BeiJing2006]狼抓兔子(最短路)
    UVa 12299 RMQ with Shifts(线段树)
    NOIP2010提高组] CODEVS 1069 关押罪犯(并查集)
    [NOIP2001提高组]CODEVS1014 Car的旅行路线(最短路)
    scp 远程文件拷贝命令
    mysql yum源安装极速
    ssh pubkey免密登陆远程主机
    paramiko linux pip18.1
    python3 linux
  • 原文地址:https://www.cnblogs.com/KimKyeYu/p/3533057.html
Copyright © 2020-2023  润新知