看了一上午才看明白,Treap = Tree + Heap,是棵弱平衡树。
一棵树同时具有二叉搜索树的性质和堆的性质,可以完成二叉搜索树和堆的操作。
有人曰:
Treap代码量小,速度较快
不能分裂合并,可以可持久化
挺好的东西。
于是我就学了。
可完成的操作:1.插入x
2.删除x数(若有多个相同的数,因只删除一个)
3.查询x数的排名(若有多个相同的数,因输出最小的排名)
4.查询排名为x的数
5.求x的前驱(前驱定义为小于x,且最大的数)
6.求x的后继(后继定义为大于x,且最小的数)
说明:
son[k][0] 表示 k 的左儿子, son[k][1] 表示 k 的右儿子
size[k] 表示以 k 为根的子树的节点数
w[k] 表示节点 k 的权值
rnd[k] 表示节点 k 的优先级
g[k] 表示节点 k 的个数(有可能有重复的)
0.旋转
最关键的操作,运用了二进制优化,使左旋和右旋代码合并。
给张左旋右旋的图,可以通过这张图来推出左旋右旋代码。(来自百度百科)
1 //通过旋转来维护小根堆 2 //因为通过旋转根是会变的,所以得加 & 3 // x 为 0 是 右旋,x 为 1 是 左旋 4 //但是不必知道是左旋还是右旋 5 //只知道旋转一个节点的孩子就相当于把这个孩子旋转到父亲上 6 void turn(int &k, int x) 7 { 8 //位运算优化 ^ 可表示兄弟节点, 使得左旋和右旋合并 9 int t = son[k][x]; 10 son[k][x] = son[t][x ^ 1]; 11 son[t][x ^ 1] = k; 12 size[t] = size[k]; 13 size[k] = size[son[k][0]] + size[son[k][1]] + g[k]; 14 k = t; 15 }