Splay Tree



類別:二叉排序樹
空間效率:O(n)
時間效率:O(log n)內完成插入、查找、刪除操作
創造者:Daniel Sleator和Robert Tarjan
優點:每次查詢會調整樹的結構,使被查詢頻率高的條目更靠近樹根。

注:所有圖片來自wiki。
http://blog.csdn.net/cyberzhg/article/details/8058208

Tree Rotation




樹的旋轉是splay的基礎,對於二叉查找樹來說,樹的旋轉不破壞查找樹的結構。

Splaying


Splaying是Splay Tree中的基本操作,爲了讓被查詢的條目更接近樹根,Splay Tree使用了樹的旋轉操作,同時保證二叉排序樹的性質不變。
Splaying的操作受以下三種因素影響:
  • 節點x是父節點p的左孩子還是右孩子
  • 節點p是不是根節點,如果不是
  • 節點p是父節點g的左孩子還是右孩子
同時有三種基本操作:

Zig Step



當p爲根節點時,進行zip step操作。
當x是p的左孩子時,對x右旋;
當x是p的右孩子時,對x左旋。

Zig-Zig Step



當p不是根節點,且x和p同爲左孩子或右孩子時進行Zig-Zig操作。
當x和p同爲左孩子時,依次將p和x右旋;
當x和p同爲右孩子時,依次將p和x左旋。


Zig-Zag Step



當p不是根節點,且x和p不同爲左孩子或右孩子時,進行Zig-Zag操作。
當p爲左孩子,x爲右孩子時,將x左旋後再右旋。
當p爲右孩子,x爲左孩子時,將x右旋後再左旋。


應用


Splay Tree可以方便的解決一些區間問題,根據不同形狀二叉樹先序遍歷結果不變的特性,可以將區間按順序建二叉查找樹。
每次自下而上的一套splay都可以將x移動到根節點的位置,利用這個特性,可以方便的利用Lazy的思想進行區間操作。
對於每個節點記錄size,代表子樹中節點的數目,這樣就可以很方便地查找區間中的第k小或第k大元素。
對於一段要處理的區間[x, y],首先splay x-1到root,再splay y+1到root的右孩子,這時root的右孩子的左孩子對應子樹就是整個區間。
這樣,大部分區間問題都可以很方便的解決,操作同樣也適用於一個或多個條目的添加或刪除,和區間的移動。


POJ2764 Feed the dogs

http://poj.org/problem?id=2764
http://blog.csdn.net/cyberzhg/article/details/8058154

區間不會重疊,所以不可能有首首相同或尾尾相同的情況,讀入所有區間,按照右端由小到大排序。然後通過維護splay進行第k小元素的查詢操作。
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <algorithm>  
  4. using namespace std;  
  5. const int MAXN = 100005;  
  6. const int MAXM = 50005;  
  7. const int INF = 0x7FFFFFFF;  
  8.   
  9. class SplayTree  
  10. {  
  11. public:  
  12.     SplayTree()  
  13.     {  
  14.         nil = &_nil;  
  15.         _nil.value = 0;  
  16.         _nil.size = 0;  
  17.         _nil.parent = nil;  
  18.         _nil.child[LEFT] = nil;  
  19.         _nil.child[RIGHT] = nil;  
  20.     }  
  21.   
  22.     inline void clear()  
  23.     {  
  24.         nodeNumber = 0;  
  25.         root = nil;  
  26.         insert(-INF);  
  27.         insert(INF);  
  28.     }  
  29.   
  30.     inline void insert(const int value)  
  31.     {  
  32.         if(root == nil)  
  33.         {  
  34.             root = newNode(nil, value);  
  35.             return;  
  36.         }  
  37.         Node *x = root;  
  38.         while(true)  
  39.         {  
  40.             int dir = x->value < value;  
  41.             if(x->child[dir] == nil)  
  42.             {  
  43.                 x->child[dir] = newNode(x, value);  
  44.                 update(x);  
  45.                 splay(x->child[dir], nil);  
  46.                 return;  
  47.             }  
  48.             else  
  49.             {  
  50.                 x = x->child[dir];  
  51.             }  
  52.         }  
  53.     }  
  54.   
  55.     inline void remove(const int value)  
  56.     {  
  57.         int k = find(value);  
  58.         find(k - 1, nil);  
  59.         find(k + 1, root);  
  60.         root->child[RIGHT]->child[LEFT] = nil;  
  61.         update(root->child[RIGHT]);  
  62.         update(root);  
  63.     }  
  64.   
  65.     inline int getKth(const int k)  
  66.     {  
  67.         find(k + 1, nil);  
  68.         return root->value;  
  69.     }  
  70.   
  71.     inline void print()  
  72.     {  
  73.         printf("Splay Tree: \n");  
  74.         print(root);  
  75.         printf("\n");  
  76.     }private:  
  77.     static const int LEFT = 0;  
  78.     static const int RIGHT = 1;  
  79.     struct Node  
  80.     {  
  81.         int value, size;  
  82.         Node *parent, *child[2];  
  83.     } _nil, node[MAXN];  
  84.     int nodeNumber;  
  85.     Node *root, *nil;  
  86.   
  87.     inline Node *newNode(Node *parent, const int value)  
  88.     {  
  89.         node[nodeNumber].value = value;  
  90.         node[nodeNumber].size = 1;  
  91.         node[nodeNumber].parent = parent;  
  92.         node[nodeNumber].child[LEFT] = nil;  
  93.         node[nodeNumber].child[RIGHT] = nil;  
  94.         return &node[nodeNumber++];  
  95.     }  
  96.   
  97.     inline void update(Node *x)  
  98.     {  
  99.         if(x == nil)  
  100.         {  
  101.             return;  
  102.         }  
  103.         x->size = x->child[LEFT]->size + x->child[RIGHT]->size + 1;  
  104.     }  
  105.   
  106.     inline void rotate(Node *x, const int dir)  
  107.     {  
  108.         Node *p = x->parent;  
  109.         p->child[!dir] = x->child[dir];  
  110.         p->child[!dir]->parent = p;  
  111.         x->child[dir] = p;  
  112.         x->parent = p->parent;  
  113.         if(p->parent->child[LEFT] == p)  
  114.         {  
  115.             p->parent->child[LEFT] = x;  
  116.         }  
  117.         else  
  118.         {  
  119.             p->parent->child[RIGHT] = x;  
  120.         }  
  121.         p->parent = x;  
  122.         update(p);  
  123.         update(x);  
  124.         if(root == p)  
  125.         {  
  126.             root = x;  
  127.         }  
  128.     }  
  129.   
  130.     inline void splay(Node *x, Node *y)  
  131.     {  
  132.         while(x->parent != y)  
  133.         {  
  134.             if(x->parent->parent == y)  
  135.             {  
  136.                 if(x->parent->child[LEFT] == x)  
  137.                 {  
  138.                     rotate(x, RIGHT);  
  139.                 }  
  140.                 else  
  141.                 {  
  142.                     rotate(x, LEFT);  
  143.                 }  
  144.             }  
  145.             else if(x->parent->parent->child[LEFT] == x->parent)  
  146.             {  
  147.                 if(x->parent->child[LEFT] == x)  
  148.                 {  
  149.                     rotate(x->parent, RIGHT);  
  150.                     rotate(x, RIGHT);  
  151.                 }  
  152.                 else  
  153.                 {  
  154.                     rotate(x, LEFT);  
  155.                     rotate(x, RIGHT);  
  156.                 }  
  157.             }  
  158.             else  
  159.             {  
  160.                 if(x->parent->child[RIGHT] == x)  
  161.                 {  
  162.                     rotate(x->parent, LEFT);  
  163.                     rotate(x, LEFT);  
  164.                 }  
  165.                 else  
  166.                 {  
  167.                     rotate(x, RIGHT);  
  168.                     rotate(x, LEFT);  
  169.                 }  
  170.             }  
  171.             update(x);  
  172.         }  
  173.     }  
  174.   
  175.     inline void find(int k, Node *y)  
  176.     {  
  177.         Node *x = root;  
  178.         while(k != x->child[LEFT]->size + 1)  
  179.         {  
  180.             if(k <= x->child[LEFT]->size)  
  181.             {  
  182.                 x = x->child[LEFT];  
  183.             }  
  184.             else  
  185.             {  
  186.                 k -= x->child[LEFT]->size + 1;  
  187.                 x = x->child[RIGHT];  
  188.             }  
  189.         }  
  190.         splay(x, y);  
  191.     }  
  192.   
  193.     inline int find(const int value)  
  194.     {  
  195.         Node *x = root;  
  196.         int count = 0;  
  197.         while(true)  
  198.         {  
  199.             if(x->value == value)  
  200.             {  
  201.                 return count + x->size - x->child[RIGHT]->size;  
  202.             }  
  203.             else if(x->value > value)  
  204.             {  
  205.                 x = x->child[LEFT];  
  206.             }  
  207.             else  
  208.             {  
  209.                 count += x->size - x->child[RIGHT]->size;  
  210.                 x = x->child[RIGHT];  
  211.             }  
  212.         }  
  213.     }  
  214.   
  215.     inline void print(Node *x)  
  216.     {  
  217.         if(x == nil)  
  218.         {  
  219.             return;  
  220.         }  
  221.         printf("%d: %d %d %d\n", x->value, x->child[LEFT]->value, x->child[RIGHT]->value, x->size);  
  222.         print(x->child[LEFT]);  
  223.         print(x->child[RIGHT]);  
  224.     }  
  225. } splay;  
  226.   
  227. struct Interval  
  228. {  
  229.     int a, b, k, index;  
  230.     bool operator < (const Interval &interval) const  
  231.     {  
  232.         return b < interval.b;  
  233.     }  
  234. } interval[MAXM];int pretty[MAXN];int ans[MAXM];  
  235.   
  236. int main()  
  237. {  
  238.     int n, m;  
  239.     while(~scanf("%d%d", &n, &m))  
  240.     {  
  241.         for(int i=1;i<=n;++i)  
  242.         {  
  243.             scanf("%d", &pretty[i]);  
  244.         }  
  245.         for(int i=0;i<m;++i)  
  246.         {  
  247.             scanf("%d%d%d", &interval[i].a, &interval[i].b, &interval[i].k);  
  248.             interval[i].index = i;  
  249.         }  
  250.         sort(interval, interval + m);  
  251.         splay.clear();  
  252.         int a = 1, b = 0;  
  253.         for(int i=0;i<m;++i)  
  254.         {  
  255.             for(int j=a;j<interval[i].a && j<=b;++j)  
  256.             {  
  257.                 splay.remove(pretty[j]);  
  258.             }  
  259.             for(int j=max(interval[i].a, b+1);j<=interval[i].b;++j)  
  260.             {  
  261.                 splay.insert(pretty[j]);  
  262.             }  
  263.             a = interval[i].a;  
  264.             b = interval[i].b;  
  265.             ans[interval[i].index] = splay.getKth(interval[i].k);  
  266.         }  
  267.         for(int i=0;i<m;++i)  
  268.         {  
  269.             printf("%d\n", ans[i]);  
  270.         }  
  271.     }  
  272.     return 0;  
  273. }  

POJ3580 SuperMemo

http://poj.org/problem?id=3580
http://blog.csdn.net/cyberzhg/article/details/8053293

在序列首尾加上值爲INF的點。一共六種操作:
1. ADD x y D
將x到y區間加上D。
利用lazy。將x-1位置splay到root,y+1位置splay到root的右孩子,這時y+1位置的左孩子就是區間的範圍。
2. REVERSE x y 反轉x到y區間
和ADD類似,記錄區間是否反轉,在需要的時候調換左右孩子。
3. REVOLVE x y T 將x到y區間循環右移T次
DELETE和INSERT的綜合,兩次區間操作。
4. INSERT x P 在x位置後插入P
和ADD類似,將區間設爲空,插入新的數值。
5. DELETE x 刪除x位置的數
和ADD類似,將最終區間設爲空。
6. MIN x y 求x到y區間中的最小值
和ADD類似,記錄所有子樹的min,在旋轉的過程中更新。

  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <algorithm>  
  4. using namespace std;  
  5. const int MAXN = 100005;  
  6. const int MAXM = 100005;  
  7. const int INF = 0x7fffffff;  
  8.   
  9. class SplayTree  
  10. {  
  11. public:  
  12.     SplayTree()  
  13.     {  
  14.         nil.size = 0;  
  15.         nil.value = INF;  
  16.         nil.min = INF;  
  17.         nil.lchild = &nil;  
  18.         nil.rchild = &nil;  
  19.         nil.parent = &nil;  
  20.     }  
  21.   
  22.     inline void make(int array[], int n)  
  23.     {  
  24.         nodeNumber = 0;  
  25.         int mid = (n - 1) >> 1;  
  26.         root = newNode(&nil, array[mid]);  
  27.         root->lchild = make(0, mid - 1, root, array);  
  28.         root->rchild = make(mid + 1, n - 1, root, array);  
  29.         update(root);  
  30.     }  
  31.   
  32.     inline void ADD(int x, int y, int D)  
  33.     {  
  34.         find(x, &nil);  
  35.         find(y + 2, root);  
  36.         root->rchild->lchild->lazy += D;  
  37.     }  
  38.   
  39.     inline void REVERSE(int x, int y)  
  40.     {  
  41.         find(x, &nil);  
  42.         find(y + 2, root);  
  43.         root->rchild->lchild->isReverse ^= true;  
  44.     }  
  45.   
  46.     inline void REVOLVE(int x, int y, int T)  
  47.     {  
  48.         int len = y - x + 1;  
  49.         T = ((T % len) + len) % len;  
  50.         if(T)  
  51.         {  
  52.             find(y - T + 1, &nil);  
  53.             find(y + 2, root);  
  54.             SplayNode *d = root->rchild->lchild;  
  55.             root->rchild->lchild = &nil;  
  56.             find(x, &nil);  
  57.             find(x + 1, root);  
  58.             root->rchild->lchild = d;  
  59.             d->parent = root->rchild;  
  60.         }  
  61.     }  
  62.   
  63.     inline void INSERT(int x, int P)  
  64.     {  
  65.         find(x + 1, &nil);  
  66.         find(x + 2, root);  
  67.         root->rchild->lchild = newNode(root->rchild, P);  
  68.     }  
  69.   
  70.     inline void DELETE(int x)  
  71.     {  
  72.         find(x, &nil);  
  73.         find(x + 2, root);  
  74.         root->rchild->lchild = &nil;  
  75.     }  
  76.   
  77.     inline void MIN(int x, int y)  
  78.     {  
  79.         find(x, &nil);  
  80.         find(y + 2, root);  
  81.         pushdown(root->rchild->lchild);  
  82.         printf("%d\n", root->rchild->lchild->min);  
  83.     }  
  84.   
  85.     inline void print()  
  86.     {  
  87.         printf("Splay Linear: \n");  
  88.         print(root);  
  89.         printf("\n");  
  90.     }  
  91.   
  92.     inline void prints()  
  93.     {  
  94.         printf("Splay Structure: \n");  
  95.         prints(root);  
  96.         printf("\n");  
  97.     }  
  98.   
  99. private:  
  100.     struct SplayNode  
  101.     {  
  102.         int value, size, lazy;  
  103.         SplayNode *parent, *lchild, *rchild;  
  104.         int min;  
  105.         bool isReverse;  
  106.     } nil, node[MAXN + MAXM];  
  107.     int nodeNumber;  
  108.     SplayNode *root;  
  109.   
  110.     inline SplayNode *newNode(SplayNode *parent, const int value)  
  111.     {  
  112.         node[nodeNumber].value = value;  
  113.         node[nodeNumber].size = 1;  
  114.         node[nodeNumber].lazy = 0;  
  115.         node[nodeNumber].parent = parent;  
  116.         node[nodeNumber].lchild = &nil;  
  117.         node[nodeNumber].rchild = &nil;  
  118.         node[nodeNumber].min = value;  
  119.         node[nodeNumber].isReverse = false;  
  120.         return &node[nodeNumber++];  
  121.     }  
  122.   
  123.     SplayNode *make(int l, int r, SplayNode *parent, int array[])  
  124.     {  
  125.         if(l > r)  
  126.         {  
  127.             return &nil;  
  128.         }  
  129.         int mid = (l + r) >> 1;  
  130.         SplayNode *x = newNode(parent, array[mid]);  
  131.         x->lchild = make(l, mid - 1, x, array);  
  132.         x->rchild = make(mid + 1, r, x, array);  
  133.         update(x);  
  134.         return x;  
  135.     }  
  136.   
  137.     inline void update(SplayNode *x)  
  138.     {  
  139.         if(x == &nil)  
  140.         {  
  141.             return;  
  142.         }  
  143.         x->size = x->lchild->size + x->rchild->size + 1;  
  144.         x->min = min(x->value, min(x->lchild->min, x->rchild->min));  
  145.     }  
  146.   
  147.     inline void pushdown(SplayNode *x)  
  148.     {  
  149.         if(x == &nil)  
  150.         {  
  151.             return;  
  152.         }  
  153.         if(x->isReverse)  
  154.         {  
  155.             swap(x->lchild, x->rchild);  
  156.             x->lchild->isReverse ^= true;  
  157.             x->rchild->isReverse ^= true;  
  158.             x->isReverse = false;  
  159.         }  
  160.         if(x->lazy)  
  161.         {  
  162.             x->value += x->lazy;  
  163.             x->min += x->lazy;  
  164.             x->lchild->lazy += x->lazy;  
  165.             x->rchild->lazy += x->lazy;  
  166.             x->lazy = 0;  
  167.         }  
  168.     }  
  169.   
  170.     inline void rotateLeft(SplayNode *x)  
  171.     {  
  172.         SplayNode *p = x->parent;  
  173.         pushdown(x->lchild);  
  174.         pushdown(x->rchild);  
  175.         pushdown(p->lchild);  
  176.         p->rchild = x->lchild;  
  177.         p->rchild->parent = p;  
  178.         x->lchild = p;  
  179.         x->parent = p->parent;  
  180.         if(p->parent->lchild == p)  
  181.         {  
  182.             p->parent->lchild = x;  
  183.         }  
  184.         else  
  185.         {  
  186.             p->parent->rchild = x;  
  187.         }  
  188.         p->parent = x;  
  189.         update(p);  
  190.         update(x);  
  191.         if(root == p)  
  192.         {  
  193.             root = x;  
  194.         }  
  195.     }  
  196.   
  197.     inline void rotateRight(SplayNode *x)  
  198.     {  
  199.         SplayNode *p = x->parent;  
  200.         pushdown(x->lchild);  
  201.         pushdown(x->rchild);  
  202.         pushdown(p->rchild);  
  203.         p->lchild = x->rchild;  
  204.         p->lchild->parent = p;  
  205.         x->rchild = p;  
  206.         x->parent = p->parent;  
  207.         if(p->parent->lchild == p)  
  208.         {  
  209.             p->parent->lchild = x;  
  210.         }  
  211.         else  
  212.         {  
  213.             p->parent->rchild = x;  
  214.         }  
  215.         p->parent = x;  
  216.         update(p);  
  217.         update(x);  
  218.         if(root == p)  
  219.         {  
  220.             root = x;  
  221.         }  
  222.     }  
  223.   
  224.     inline void splay(SplayNode *x, SplayNode *y)  
  225.     {  
  226.         pushdown(x);  
  227.         while(x->parent != y)  
  228.         {  
  229.             if(x->parent->parent == y)  
  230.             {  
  231.                 if(x->parent->lchild == x)  
  232.                 {  
  233.                     rotateRight(x);  
  234.                 }  
  235.                 else  
  236.                 {  
  237.                     rotateLeft(x);  
  238.                 }  
  239.             }  
  240.             else if(x->parent->parent->lchild == x->parent)  
  241.             {  
  242.                 if(x->parent->lchild == x)  
  243.                 {  
  244.                     rotateRight(x->parent);  
  245.                     rotateRight(x);  
  246.                 }  
  247.                 else  
  248.                 {  
  249.                     rotateLeft(x);  
  250.                     rotateRight(x);  
  251.                 }  
  252.             }  
  253.             else  
  254.             {  
  255.                 if(x->parent->rchild == x)  
  256.                 {  
  257.                     rotateLeft(x->parent);  
  258.                     rotateLeft(x);  
  259.                 }  
  260.                 else  
  261.                 {  
  262.                     rotateRight(x);  
  263.                     rotateLeft(x);  
  264.                 }  
  265.             }  
  266.         }  
  267.         update(x);  
  268.     }  
  269.   
  270.     inline void find(int k, SplayNode *y)  
  271.     {  
  272.         SplayNode *x = root;  
  273.         pushdown(x);  
  274.         while(k != x->lchild->size + 1)  
  275.         {  
  276.             if(k <= x->lchild->size)  
  277.             {  
  278.                 x = x->lchild;  
  279.             }  
  280.             else  
  281.             {  
  282.                 k -= x->lchild->size + 1;  
  283.                 x = x->rchild;  
  284.             }  
  285.             pushdown(x);  
  286.         }  
  287.         splay(x, y);  
  288.     }  
  289.   
  290.     inline void print(SplayNode *x)  
  291.     {  
  292.         if(x == &nil)  
  293.         {  
  294.             return;  
  295.         }  
  296.         pushdown(x);  
  297.         print(x->lchild);  
  298.         printf("%d: %d %d %d %d\n", x->value, x->min, x->parent->value, x->lchild->value, x->rchild->value);  
  299.         print(x->rchild);  
  300.     }  
  301.   
  302.     inline void prints(SplayNode *x)  
  303.     {  
  304.         if(x == &nil)  
  305.         {  
  306.             return;  
  307.         }  
  308.         pushdown(x);  
  309.         if(x->value == INF)  
  310.         {  
  311.             printf("INF : ");  
  312.         }  
  313.         else  
  314.         {  
  315.             printf("%d : ", x->value);  
  316.         }  
  317.         if(x->lchild == &nil)  
  318.         {  
  319.             printf("nil ");  
  320.         }  
  321.         else  
  322.         {  
  323.             if(x->lchild->value == INF)  
  324.             {  
  325.                 printf("INF ");  
  326.             }  
  327.             else  
  328.             {  
  329.                 printf("%d ", x->lchild->value);  
  330.             }  
  331.         }  
  332.         if(x->rchild == &nil)  
  333.         {  
  334.             printf("nil\n");  
  335.         }  
  336.         else  
  337.         {  
  338.             if(x->rchild->value == INF)  
  339.             {  
  340.                 printf("INF\n");  
  341.             }  
  342.             else  
  343.             {  
  344.                 printf("%d\n", x->rchild->value);  
  345.             }  
  346.         }  
  347.         prints(x->lchild);  
  348.         prints(x->rchild);  
  349.     }  
  350. } splayTree;  
  351.   
  352. char buffer[128];int array[MAXN];int n, m;  
  353.   
  354. int main()  
  355. {  
  356.     int x, y, D, T, P;  
  357.     scanf("%d", &n);  
  358.     for(int i=1;i<=n;++i)  
  359.     {  
  360.         scanf("%d", &array[i]);  
  361.     }  
  362.     array[0] = INF;  
  363.     array[n+1] = INF;  
  364.     splayTree.make(array, n + 2);  
  365.     scanf("%d", &m);  
  366.     while(m--)  
  367.     {  
  368.         scanf("%s", buffer);  
  369.         switch(buffer[0])  
  370.         {  
  371.         case 'A':  
  372.             scanf("%d%d%d", &x, &y, &D);  
  373.             splayTree.ADD(x, y, D);  
  374.             break;  
  375.         case 'R':  
  376.             if('E' == buffer[3])  
  377.             {  
  378.                 scanf("%d%d", &x, &y);  
  379.                 splayTree.REVERSE(x, y);  
  380.             }  
  381.             else  
  382.             {  
  383.                 scanf("%d%d%d", &x, &y, &T);  
  384.                 splayTree.REVOLVE(x, y, T);  
  385.             }  
  386.             break;  
  387.         case 'I':  
  388.             scanf("%d%d", &x, &P);  
  389.             splayTree.INSERT(x, P);  
  390.             break;  
  391.         case 'D':  
  392.             scanf("%d", &x);  
  393.             splayTree.DELETE(x);  
  394.             break;  
  395.         case 'M':  
  396.             scanf("%d%d", &x, &y);  
  397.             splayTree.MIN(x, y);  
  398.             break;  
  399.         }  
  400.     }  
  401.     return 0;  
  402. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章