Splay Tree
类别:二叉排序树
时间效率:O(log n)内完成插入、查找、删除操作
注:所有图片来自wiki。
Tree Rotation
![](https://img-my.csdn.net/uploads/201210/10/1349877565_2986.png)
Splaying
- 节点x是父节点p的左孩子还是右孩子
- 节点p是不是根节点,如果不是
- 节点p是父节点g的左孩子还是右孩子
Zig Step
![](https://img-my.csdn.net/uploads/201210/10/1349877709_4105.png)
Zig-Zig Step
![](https://img-my.csdn.net/uploads/201210/10/1349877744_7090.png)
Zig-Zag Step
![](https://img-my.csdn.net/uploads/201210/10/1349877779_5253.png)
应用
POJ2764 Feed the dogs
http://blog.csdn.net/cyberzhg/article/details/8058154
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- using namespace std;
- const int MAXN = 100005;
- const int MAXM = 50005;
- const int INF = 0x7FFFFFFF;
- class SplayTree
- {
- public:
- SplayTree()
- {
- nil = &_nil;
- _nil.value = 0;
- _nil.size = 0;
- _nil.parent = nil;
- _nil.child[LEFT] = nil;
- _nil.child[RIGHT] = nil;
- }
- inline void clear()
- {
- nodeNumber = 0;
- root = nil;
- insert(-INF);
- insert(INF);
- }
- inline void insert(const int value)
- {
- if(root == nil)
- {
- root = newNode(nil, value);
- return;
- }
- Node *x = root;
- while(true)
- {
- int dir = x->value < value;
- if(x->child[dir] == nil)
- {
- x->child[dir] = newNode(x, value);
- update(x);
- splay(x->child[dir], nil);
- return;
- }
- else
- {
- x = x->child[dir];
- }
- }
- }
- inline void remove(const int value)
- {
- int k = find(value);
- find(k - 1, nil);
- find(k + 1, root);
- root->child[RIGHT]->child[LEFT] = nil;
- update(root->child[RIGHT]);
- update(root);
- }
- inline int getKth(const int k)
- {
- find(k + 1, nil);
- return root->value;
- }
- inline void print()
- {
- printf("Splay Tree: \n");
- print(root);
- printf("\n");
- }private:
- static const int LEFT = 0;
- static const int RIGHT = 1;
- struct Node
- {
- int value, size;
- Node *parent, *child[2];
- } _nil, node[MAXN];
- int nodeNumber;
- Node *root, *nil;
- inline Node *newNode(Node *parent, const int value)
- {
- node[nodeNumber].value = value;
- node[nodeNumber].size = 1;
- node[nodeNumber].parent = parent;
- node[nodeNumber].child[LEFT] = nil;
- node[nodeNumber].child[RIGHT] = nil;
- return &node[nodeNumber++];
- }
- inline void update(Node *x)
- {
- if(x == nil)
- {
- return;
- }
- x->size = x->child[LEFT]->size + x->child[RIGHT]->size + 1;
- }
- inline void rotate(Node *x, const int dir)
- {
- Node *p = x->parent;
- p->child[!dir] = x->child[dir];
- p->child[!dir]->parent = p;
- x->child[dir] = p;
- x->parent = p->parent;
- if(p->parent->child[LEFT] == p)
- {
- p->parent->child[LEFT] = x;
- }
- else
- {
- p->parent->child[RIGHT] = x;
- }
- p->parent = x;
- update(p);
- update(x);
- if(root == p)
- {
- root = x;
- }
- }
- inline void splay(Node *x, Node *y)
- {
- while(x->parent != y)
- {
- if(x->parent->parent == y)
- {
- if(x->parent->child[LEFT] == x)
- {
- rotate(x, RIGHT);
- }
- else
- {
- rotate(x, LEFT);
- }
- }
- else if(x->parent->parent->child[LEFT] == x->parent)
- {
- if(x->parent->child[LEFT] == x)
- {
- rotate(x->parent, RIGHT);
- rotate(x, RIGHT);
- }
- else
- {
- rotate(x, LEFT);
- rotate(x, RIGHT);
- }
- }
- else
- {
- if(x->parent->child[RIGHT] == x)
- {
- rotate(x->parent, LEFT);
- rotate(x, LEFT);
- }
- else
- {
- rotate(x, RIGHT);
- rotate(x, LEFT);
- }
- }
- update(x);
- }
- }
- inline void find(int k, Node *y)
- {
- Node *x = root;
- while(k != x->child[LEFT]->size + 1)
- {
- if(k <= x->child[LEFT]->size)
- {
- x = x->child[LEFT];
- }
- else
- {
- k -= x->child[LEFT]->size + 1;
- x = x->child[RIGHT];
- }
- }
- splay(x, y);
- }
- inline int find(const int value)
- {
- Node *x = root;
- int count = 0;
- while(true)
- {
- if(x->value == value)
- {
- return count + x->size - x->child[RIGHT]->size;
- }
- else if(x->value > value)
- {
- x = x->child[LEFT];
- }
- else
- {
- count += x->size - x->child[RIGHT]->size;
- x = x->child[RIGHT];
- }
- }
- }
- inline void print(Node *x)
- {
- if(x == nil)
- {
- return;
- }
- printf("%d: %d %d %d\n", x->value, x->child[LEFT]->value, x->child[RIGHT]->value, x->size);
- print(x->child[LEFT]);
- print(x->child[RIGHT]);
- }
- } splay;
- struct Interval
- {
- int a, b, k, index;
- bool operator < (const Interval &interval) const
- {
- return b < interval.b;
- }
- } interval[MAXM];int pretty[MAXN];int ans[MAXM];
- int main()
- {
- int n, m;
- while(~scanf("%d%d", &n, &m))
- {
- for(int i=1;i<=n;++i)
- {
- scanf("%d", &pretty[i]);
- }
- for(int i=0;i<m;++i)
- {
- scanf("%d%d%d", &interval[i].a, &interval[i].b, &interval[i].k);
- interval[i].index = i;
- }
- sort(interval, interval + m);
- splay.clear();
- int a = 1, b = 0;
- for(int i=0;i<m;++i)
- {
- for(int j=a;j<interval[i].a && j<=b;++j)
- {
- splay.remove(pretty[j]);
- }
- for(int j=max(interval[i].a, b+1);j<=interval[i].b;++j)
- {
- splay.insert(pretty[j]);
- }
- a = interval[i].a;
- b = interval[i].b;
- ans[interval[i].index] = splay.getKth(interval[i].k);
- }
- for(int i=0;i<m;++i)
- {
- printf("%d\n", ans[i]);
- }
- }
- return 0;
- }
POJ3580 SuperMemo
http://blog.csdn.net/cyberzhg/article/details/8053293
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- using namespace std;
- const int MAXN = 100005;
- const int MAXM = 100005;
- const int INF = 0x7fffffff;
- class SplayTree
- {
- public:
- SplayTree()
- {
- nil.size = 0;
- nil.value = INF;
- nil.min = INF;
- nil.lchild = &nil;
- nil.rchild = &nil;
- nil.parent = &nil;
- }
- inline void make(int array[], int n)
- {
- nodeNumber = 0;
- int mid = (n - 1) >> 1;
- root = newNode(&nil, array[mid]);
- root->lchild = make(0, mid - 1, root, array);
- root->rchild = make(mid + 1, n - 1, root, array);
- update(root);
- }
- inline void ADD(int x, int y, int D)
- {
- find(x, &nil);
- find(y + 2, root);
- root->rchild->lchild->lazy += D;
- }
- inline void REVERSE(int x, int y)
- {
- find(x, &nil);
- find(y + 2, root);
- root->rchild->lchild->isReverse ^= true;
- }
- inline void REVOLVE(int x, int y, int T)
- {
- int len = y - x + 1;
- T = ((T % len) + len) % len;
- if(T)
- {
- find(y - T + 1, &nil);
- find(y + 2, root);
- SplayNode *d = root->rchild->lchild;
- root->rchild->lchild = &nil;
- find(x, &nil);
- find(x + 1, root);
- root->rchild->lchild = d;
- d->parent = root->rchild;
- }
- }
- inline void INSERT(int x, int P)
- {
- find(x + 1, &nil);
- find(x + 2, root);
- root->rchild->lchild = newNode(root->rchild, P);
- }
- inline void DELETE(int x)
- {
- find(x, &nil);
- find(x + 2, root);
- root->rchild->lchild = &nil;
- }
- inline void MIN(int x, int y)
- {
- find(x, &nil);
- find(y + 2, root);
- pushdown(root->rchild->lchild);
- printf("%d\n", root->rchild->lchild->min);
- }
- inline void print()
- {
- printf("Splay Linear: \n");
- print(root);
- printf("\n");
- }
- inline void prints()
- {
- printf("Splay Structure: \n");
- prints(root);
- printf("\n");
- }
- private:
- struct SplayNode
- {
- int value, size, lazy;
- SplayNode *parent, *lchild, *rchild;
- int min;
- bool isReverse;
- } nil, node[MAXN + MAXM];
- int nodeNumber;
- SplayNode *root;
- inline SplayNode *newNode(SplayNode *parent, const int value)
- {
- node[nodeNumber].value = value;
- node[nodeNumber].size = 1;
- node[nodeNumber].lazy = 0;
- node[nodeNumber].parent = parent;
- node[nodeNumber].lchild = &nil;
- node[nodeNumber].rchild = &nil;
- node[nodeNumber].min = value;
- node[nodeNumber].isReverse = false;
- return &node[nodeNumber++];
- }
- SplayNode *make(int l, int r, SplayNode *parent, int array[])
- {
- if(l > r)
- {
- return &nil;
- }
- int mid = (l + r) >> 1;
- SplayNode *x = newNode(parent, array[mid]);
- x->lchild = make(l, mid - 1, x, array);
- x->rchild = make(mid + 1, r, x, array);
- update(x);
- return x;
- }
- inline void update(SplayNode *x)
- {
- if(x == &nil)
- {
- return;
- }
- x->size = x->lchild->size + x->rchild->size + 1;
- x->min = min(x->value, min(x->lchild->min, x->rchild->min));
- }
- inline void pushdown(SplayNode *x)
- {
- if(x == &nil)
- {
- return;
- }
- if(x->isReverse)
- {
- swap(x->lchild, x->rchild);
- x->lchild->isReverse ^= true;
- x->rchild->isReverse ^= true;
- x->isReverse = false;
- }
- if(x->lazy)
- {
- x->value += x->lazy;
- x->min += x->lazy;
- x->lchild->lazy += x->lazy;
- x->rchild->lazy += x->lazy;
- x->lazy = 0;
- }
- }
- inline void rotateLeft(SplayNode *x)
- {
- SplayNode *p = x->parent;
- pushdown(x->lchild);
- pushdown(x->rchild);
- pushdown(p->lchild);
- p->rchild = x->lchild;
- p->rchild->parent = p;
- x->lchild = p;
- x->parent = p->parent;
- if(p->parent->lchild == p)
- {
- p->parent->lchild = x;
- }
- else
- {
- p->parent->rchild = x;
- }
- p->parent = x;
- update(p);
- update(x);
- if(root == p)
- {
- root = x;
- }
- }
- inline void rotateRight(SplayNode *x)
- {
- SplayNode *p = x->parent;
- pushdown(x->lchild);
- pushdown(x->rchild);
- pushdown(p->rchild);
- p->lchild = x->rchild;
- p->lchild->parent = p;
- x->rchild = p;
- x->parent = p->parent;
- if(p->parent->lchild == p)
- {
- p->parent->lchild = x;
- }
- else
- {
- p->parent->rchild = x;
- }
- p->parent = x;
- update(p);
- update(x);
- if(root == p)
- {
- root = x;
- }
- }
- inline void splay(SplayNode *x, SplayNode *y)
- {
- pushdown(x);
- while(x->parent != y)
- {
- if(x->parent->parent == y)
- {
- if(x->parent->lchild == x)
- {
- rotateRight(x);
- }
- else
- {
- rotateLeft(x);
- }
- }
- else if(x->parent->parent->lchild == x->parent)
- {
- if(x->parent->lchild == x)
- {
- rotateRight(x->parent);
- rotateRight(x);
- }
- else
- {
- rotateLeft(x);
- rotateRight(x);
- }
- }
- else
- {
- if(x->parent->rchild == x)
- {
- rotateLeft(x->parent);
- rotateLeft(x);
- }
- else
- {
- rotateRight(x);
- rotateLeft(x);
- }
- }
- }
- update(x);
- }
- inline void find(int k, SplayNode *y)
- {
- SplayNode *x = root;
- pushdown(x);
- while(k != x->lchild->size + 1)
- {
- if(k <= x->lchild->size)
- {
- x = x->lchild;
- }
- else
- {
- k -= x->lchild->size + 1;
- x = x->rchild;
- }
- pushdown(x);
- }
- splay(x, y);
- }
- inline void print(SplayNode *x)
- {
- if(x == &nil)
- {
- return;
- }
- pushdown(x);
- print(x->lchild);
- printf("%d: %d %d %d %d\n", x->value, x->min, x->parent->value, x->lchild->value, x->rchild->value);
- print(x->rchild);
- }
- inline void prints(SplayNode *x)
- {
- if(x == &nil)
- {
- return;
- }
- pushdown(x);
- if(x->value == INF)
- {
- printf("INF : ");
- }
- else
- {
- printf("%d : ", x->value);
- }
- if(x->lchild == &nil)
- {
- printf("nil ");
- }
- else
- {
- if(x->lchild->value == INF)
- {
- printf("INF ");
- }
- else
- {
- printf("%d ", x->lchild->value);
- }
- }
- if(x->rchild == &nil)
- {
- printf("nil\n");
- }
- else
- {
- if(x->rchild->value == INF)
- {
- printf("INF\n");
- }
- else
- {
- printf("%d\n", x->rchild->value);
- }
- }
- prints(x->lchild);
- prints(x->rchild);
- }
- } splayTree;
- char buffer[128];int array[MAXN];int n, m;
- int main()
- {
- int x, y, D, T, P;
- scanf("%d", &n);
- for(int i=1;i<=n;++i)
- {
- scanf("%d", &array[i]);
- }
- array[0] = INF;
- array[n+1] = INF;
- splayTree.make(array, n + 2);
- scanf("%d", &m);
- while(m--)
- {
- scanf("%s", buffer);
- switch(buffer[0])
- {
- case 'A':
- scanf("%d%d%d", &x, &y, &D);
- splayTree.ADD(x, y, D);
- break;
- case 'R':
- if('E' == buffer[3])
- {
- scanf("%d%d", &x, &y);
- splayTree.REVERSE(x, y);
- }
- else
- {
- scanf("%d%d%d", &x, &y, &T);
- splayTree.REVOLVE(x, y, T);
- }
- break;
- case 'I':
- scanf("%d%d", &x, &P);
- splayTree.INSERT(x, P);
- break;
- case 'D':
- scanf("%d", &x);
- splayTree.DELETE(x);
- break;
- case 'M':
- scanf("%d%d", &x, &y);
- splayTree.MIN(x, y);
- break;
- }
- }
- return 0;
- }
Splay Tree相关推荐
- BZOJ1500 [NOI2005]维修数列(Splay tree)
[Submit][Status][Discuss] Description 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线' _ '表示实际输入文件中的空格 Inp ...
- 伸展树(Splay tree)图解与实现
伸展树(Splay tree)图解与实现 伸展树(Splay tree)图解与实现_小张的专栏-CSDN博客_splay树 Splay树详解 Splay树详解 - 秦淮岸灯火阑珊 - 博客园 平衡树 ...
- poj 2892 Tunnel Warfare (Splay Tree instead of Segment Tree)
poj.org/problem?id=2892 poj上的一道数据结构题,这题正解貌似是Segment Tree,不过我用了Splay Tree来写,而且我个人认为,这题用Splay Tree会更好写 ...
- [HNOI2002]营业额统计 Splay tree入门题
[HNOI2002]营业额统计 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588 [HNOI2002]营业额统计 Time Limit ...
- splay tree java移除_Splay Tree的删除操作
Splay Tree的插入操作,搜索操作,和删除操作都实现了,那么就能够使用来解题了. 指针的删除操作的处理还是那么难的,非常多坎须要避开. 同一个坎还是坑了我好多次,就是指针传递的问题,什么时候须要 ...
- splay tree java_伸展树(splay tree)自顶向下的算法
伸展树(splay tree)是一种能自我调整的二叉搜索树(BST).虽然某一次的访问操作所花费的时间比较长,但是平摊(amortized) 之后的访问操作(例如旋转)时间能达到O(logn)的复杂度 ...
- 伸展树(Splay Tree)尽收眼底
原文地址:http://dsqiu.iteye.com/blog/1706592 伸展树(Splay Tree)尽收眼底 本文内容框架: §1 伸展树定义 §2 伸展树自底向上伸展 §3 伸展树自 ...
- 伸展树(Splay tree)浅谈
树看的越来越多,越来越神奇. 看伸展树这种神级数据结构之前,建议大家首先彻底明白二叉搜索树,这是万树的基础. 然后可以去看下treap,最好再去看下红黑树.如果有线段树的基础那更好了,我们会发现线段树 ...
- Splay Tree伸展树
伸展树基本概念 伸展树的基本思想. 伸展树完全是基于局部性原理(locality)的. 局部性原理是计算机科学中非常重要的原理,很多设计,比如说多级存储器,缓存,都是基于局部性原理.简单说来就是< ...
最新文章
- PHP Session中保存Object
- mysql登录之后可以写什么_MYSQL登陆完之后如何操作???(新手求助)
- 谈谈关于MVP模式中V-P交互问题
- 使用ASP.NET 2.0 Profile存储用户信息
- Java集合系列---List源码解析(ArrayList和LinkedList的区别)
- PMOS 和 NMOS区别
- java 蓝桥杯算法训练 未名湖边的烦恼
- Java基础——基本类型和包装类、基本类型和字符串之间的转换
- 拓端tecdat|R语言GARCH-DCC模型和DCC(MVT)建模估计
- [转载] 中华典故故事(孙刚)——33 人上一百形形色色
- 程序员面试宝典及Java面试题解析2021年
- django+layui表格数据管理
- 记录一下3dmax--substancePainter-unity烘焙法线详细过程
- 数据结构——图的邻接矩阵实现
- 【产品】设计时可用到的认知偏差与效应
- 如何选择终端桌面管理软件?
- unity球体添加光源_关于Unity中的光源
- 小猿君的面试细节课堂(第二节)
- DefCampCTF2122取证
- 安装Souce Insight 4.0 、显示文件浏览、折叠代码