平衡树注意事项
FHQ Treap
- 按值分裂时,不要把
if (tr[tr[u].l].size + 1 <= size)写成if (tr[u].size + 1 <= size)。 pushup的时候,记得加上if (!u) return ;防止出现边界错误。- 查询值的排名的时候,是
size(x) + 1,不要忘记+1。 - 不要忘记
root = merge(...);,最好直接分裂合并成对写。 pushdown不关要写在操作函数,只要是递归了就要写,包括输出函数。
Splay
- yxc写法里面,
insert的末尾不用pushup(p)是因为一定会把u转到根,也就是一定会和p交换,而交换之后是先pushup(p)再pushup(u),就是正确的了;当然看着难受,可以加上pushup。 - 查找指定排名的值时,递归右子树,忘记减去左子树和根对大小的贡献。
splay函数末尾if (!k)写成if (k ^ 1)。
2022.12.18
这份代码调了将近2h,终于知到自己打平衡树多难了TQT……
总结一下:
- 但凡手动改变了
tr数组的值(调用rotate和splay函数的不算,因为里面会pushup),都要手动pushup一遍; - 同时查询多个值并对树进行修改时,要先全部查询完,再来处理修改,不然第二个查询的值就不是原树的值了,而是进行了第一个修改的值(比如上面代码的
Top/Bottom操作的两个get_k)。 - 上面这题的
Insert操作,相当于交换两个节点的位置,很值得学习,忘记写tr[v].p=0,但是其实只要照着结构体的每个变量,一个个按照新树的结构进行交换,是可以避免忘记写的。
2022.12.24
Splay找前驱和后继的时候不用很麻烦的递归,因为这样还要考虑父节点是不是后继。可以直接把要求前驱后继的点x转到根,这样就没有父结点了,直接左儿子向右走,右儿子向左走就行了。
2022.12.26
here,看注释。
插入一段区间之后一定不要忘记Splay是双向链表,有一个p的值要更新。

浙公网安备 33010602011771号