? ! 无需旋转和合并的平衡树 ?!
这个东西比替罪羊的优势是支持可持久化。
双值版
这个东西跟先序遍历平衡树一样,做不了区间翻转。
事实上,它更像权值线段树。
这个东西的每个节点需要像线段树一样维护一个值域上的区间,还要维护两个值,左中值和右中值,分别表示左边跟 mid 最接近的和右边跟 mid 最接近的。
插入时,如果发现新插入的值比目前维护的左中值或右中值更靠近 mid,那么就 swap 一下,然后往左右儿子递归。
如果现在这里没有点,就新建一个,根据值在左边还是在右边决定是左中值还是右中值。
删除可以考虑维护 cnt ,然后找到对应的点,减一下 cnt,不过应该是有更真的实现的,比如把左边的最大值拿上来充当新的左中值,但是如果不维护 cnt 的话,同一个值插入很多次会出问题,需要一些手法,所以我没写。
kth 之类的操作也是好做的,跟其他平衡树差不多,不过因为它在中间有两个值,所以会难写一点。
复杂度显然是对的,因为这个东西结构就是类似于线段树的,常熟也不大,跑得跟红黑树差不了多少,如果实现精细应该可以更快。
这个东西的空间是严格
不过其实它最大的作用是比权值线段树空间少个
应该是可以做绝大部分权值线段树支持做的东西的。
提交记录(8.22s)
单值版
存在只维护一个中值的实现,具体来讲就是我们发现只需要这个中值是左中值和右中值任意之一,也就是
注意,这个是递归建的,所以可能原树存在更接近
所以我们记一下每个点维护的是左中值还是右中值,然后只在插入的点在 mid 的同一侧且更近的时候再交换。
这样就感觉不比一般平衡树难写了。
感觉这个东西比 fhq-treap 好写,有没有感觉。
提交记录(8.53s)
不过不知道为啥跑的更慢,可能是树高卡的更满导致的。
这个东西在值域为
这个性质可能有些奇怪的用途。
upd:我错了,这个跑得比红黑树快,带快读喜提 6.08s。
先序版
考虑把这个东西改成先序遍历的,如果插入值小于当前值就 swap 一下,如果新的插入值在
复杂度显然还是对的,于是我们就成功爆了曾经的先序遍历平衡树。
还是比红黑树快,但是不知道为啥跑的更慢了
upd: 卡常成果
跟 treap 的关联
如果你将
这个思路非常的优秀,如果我们发现加的点的优先级不满足堆性质,那为啥不改一下优先级呢?
未来
这个东西可能支持调整优先级,如上升优先级就是把最大/最小值拿上来,下降优先级就是反过来,所以可能可以支持 2 个 log 的合并,但似乎比较复杂,鉴定为不如 fhq。