好像是一种非常重要的数据结构……?
哦Splay本质其实是颗二叉查找树。
什么是二叉查找树?
定义……记住就好了。就是一棵树(空树也是二叉查找树……)
对于一棵树的任意结点
若左子树不为空,则左子树的值都小于该节点的值
若右子树不为空,则右子树的值都大于该节点的值
树中没有权值相同的节点(因为相同的权值都被合并在一个节点上了,不过讲道理也可以等于,记得做过一个题,只不过可能处理起来比较麻烦)。
SplayNB在哪里?
普通的二叉查找树很容易被卡……比如输入数据递增/递减,那么就被卡成树高为n了emm
而Splay可以让树不断旋转,以维持这棵树不过高
普通二叉查找树的操作=w=
懒得写了……普通二叉查找树的操作非常好懂网上就有
Splay的旋转操作
对于节点x,我们改变其祖父和父亲的值。
1、如果三点一线先转父亲,否则就先转x。 2、转x
重复上面的步骤,改变他们的父子关系。这样一直把x做到根。
很容易发现这棵树的中序遍历是不会改变的(这非常重要)
那么二叉查找树的性质仍然满足,只不过树高被调整了。
Splay的二叉查找树操作
这个很简单,和普通二叉查找树一样,只不过对一个点x操作过后,将其splay到根以保证树高不过高就好了。
Splay的区间操作
这里一开始并不是很理解,但只要知道一棵树旋转操作是不会改变其中序遍历的。
那么我们用中序遍历保存原序列,然后就可以和线段树一样打标记pushdown还有pushup维护区间信息了。
假设想操作区间[l,r],我们就将l-1,r+1的点分别转到根/根的右儿子
那么r+1有且仅有一个儿子,为左儿子。左儿子的子树就是我们要找的区间,然后就可以在上面打标记操作了。
为了防止越界,设定1和n+2节点为哨兵节点。那么若要将l-1,r+1的点分别转到根/根的右儿子,则变成了操作树上的l节点和r+2节点转上去