平衡树注意事项

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……

总结一下:

  1. 但凡手动改变了tr数组的值(调用rotatesplay函数的不算,因为里面会pushup),都要手动pushup一遍;
  2. 同时查询多个值并对树进行修改时,要先全部查询完,再来处理修改,不然第二个查询的值就不是原树的值了,而是进行了第一个修改的值(比如上面代码的Top/Bottom操作的两个get_k)。
  3. 上面这题的Insert操作,相当于交换两个节点的位置,很值得学习,忘记写tr[v].p=0,但是其实只要照着结构体的每个变量,一个个按照新树的结构进行交换,是可以避免忘记写的。

2022.12.24

Splay找前驱和后继的时候不用很麻烦的递归,因为这样还要考虑父节点是不是后继。可以直接把要求前驱后继的点x转到根,这样就没有父结点了,直接左儿子向右走,右儿子向左走就行了。

2022.12.26

here,看注释。
插入一段区间之后一定不要忘记Splay是双向链表,有一个p的值要更新。

posted @ 2022-12-05 20:43  Zlc晨鑫  阅读(38)  评论(0)    收藏  举报