前言
学了 FHQ Treap ,据说那玩意能代替 Splay,所以就懒得学Splay 了 = =,直到老吕给我们讲了 Splay,发现这玩意确实也挺香滴 /se
这儿主要参考 attack 学长的博客,所以这就不再详细写了(主要是懒)
简介
Splay 也是平衡树的一种,所以它还是基于二叉搜索树的
主要思想:对于查找频率较高的节点,使其处于离根节点相对较近的节点
Splay 的特色操作:rotate 和 Splay
操作
具体操作和 Treap 类似,但是这不是父亲向下挪,而是儿子向上挪(效果其实一个样),相比于 Treap,Splay 要维护每个点父亲的信息
rotate
使得一个点挪到它的父亲节点
- 当 X 是 Y 的左孩子
R R
\ Y X
/ -> / X A Y
/ \ / A B B C
- 当 X 是 Y 的右孩子
R R
\ Y X
/ \ -> / A X Y C
/ \ / B C A B
发现:如果让 X 成为 Y 的父亲,只会影响三个点关系,B 与 X, X 与Y, X 和 R
规律:
B 成为 Y 的哪个儿子与 X 是 Y 的哪个儿子是一样的
Y 成为 X 的哪个儿子与 X 是 Y 的哪个儿子相反
X 成为 R 的哪个儿子与 Y 是 R 的哪个儿子相同
那么只需要得出每个点是它父亲的什么儿子就好了
Splay
把 x 节点挪到 to 节点
- 如果 to 是 x 的爸爸,直接把 x 旋上去
- 如果 x 和它爸爸,爷爷在同一条直线就先旋父亲,再旋儿子
- 若 x 和它爸爸,爷爷不在同一条直线上,旋两次 x 就好
Insert
在二叉树中找到它的位置,插入,然后把它转到根节点,就好了
Delete
找到目标节点,把它转到根,分情况讨论
- 该节点有重复值,直接减
- 它没有左右儿子:直接删
- 它没有左儿子:把根置为右儿子
- 它既有左儿子,也有右儿子:在左儿子中找到最大值,旋转到根,右儿子当做新根的右儿子
Rank
找到它的位置,根据子树大小确定它的排名
Kth
根据子树大小确定它的位置
query pre(rec)
和 Treap 一个样
至于代码
还没加工出来 = =