可并堆
0x00 简介
- 顾名思义咯,可以在O(logn)甚至O(1)时间内合并的堆
- 也没什么好说的
0x01 左偏树
- 一种特殊的堆,要求左子树的距离大于右子树的距离
- 具体实现也很奇怪,像是非旋treap那样合并
- 最恶劣情况下的树高是O(n),暴力往上爬是不可取的,需要额外开一个并查集维护根节点
- 我不太想讲这个,因为常数大而且不好理解
- 不过板子我写了,可以看代码
0x02 配对堆
- 说实话,这个东西的思路很多人在初学二叉堆的时候都有过
- 回忆一下向二叉堆里插入一个数的情况,我们把这个数放在size+1这个位置,然后通过一些调整维护堆的性质
- 那为什么我们不直接像并查集一样,把这个数挂到根节点下面呢?(也可能是把根节点挂到这个点下面)
- 这样子插入就变成O(1)了对吧?
- 这样的话,假设我们维护的是一个小根堆,如果我们要减少某个数的值,只要把以它为根的子树拆出来,然后再和根合并就行了对吧?这个操作也是O(1)的
- 取最大/最小元素自然不必说,也是O(1)的
- 唯一的问题在于,如何pop出一个元素
- 由于我们直接把数合并到根节点上,一个节点可能不止有两个儿子,这会导致如果我们想要像二叉堆那样调整,复杂度会退化成一个非常恐怖的值,求导了半天算出来是\(latex O(e^{\frac{n}{e}})\)
- 我们有个很妙的做法,把儿子两两合并起来,用最后的结果取代原来的根,这样做是O(n)的
- 然而,如果我们这样做完的结果让儿子分配的更平均(儿子被均匀的分开,没有一个节点儿子特别多)了,显然下一次的合并的复杂度就会更优
- 我们考虑一个点u,她的儿子是{1,2,3,4,5,6,7,8}
- 然后我们做这样的操作
- {1,2,3,4,5,6,7,8}
- {3,4,5,6,7,8,{1,2}}
- {5,6,7,8,{1,2},{3,4}}
- {7,8,{1,2},{3,4},{5,6}}
- {{1,2},{3,4},{5,6},{7,8}}
- {{5,6},{7,8},{1,2,3,4}}
- {{1,2,3,4},{5,6,7,8}}
- {{1,2,3,4,5,6,7,8}}
- 你可能已经看出来了,不断地从队首取两个元素出来合并起来,把合并完的结果丢到队尾,直到队中只有一个元素
- 显然,这样至少会把儿子平均分成两半
- 然后pop操作就是均摊log了
- 然后我们就可以维护一些有趣的操作,比如在小根堆里把一个数增加一个值
- 把她从堆里拆出来,然后把她pop出来,再合并回去
- 总体来说是很好写的,我们采用父亲-兄弟存图的方法,对于一个点维护一下它的前驱,后继,父亲,第一个儿子,pop的时候把所有儿子拆下来丢进一个队列里,合并的时候讨论一下就行了
- 然而树高还是最坏O(n)的,还是需要并查集辅助
0x03 拓展!
- 如果我们想要做一类要求合并联通块,单点修改,联通块修改,全局修改,单点查询,联通块查询,全局查询的问题(我说的就是棘手的操作),并且要求强制在线(不然直接线段树就好了)的问题,我们要怎么搞呢?
- 我们需要一个神奇的堆套堆
- 分别考虑每种操作和询问,注意每个操作中都要维护可并堆的根
- 合并联通块:把两个可并堆并起来,并查集也并起来,并且对标记差分(下面会讲)
- 单点修改:拆出来,pop,修改,并回去
- 联通块修改:这是重点,由于我们不能做标记下传,我们需要标记永久化,标价在哪呢?不能打在可并堆上,因为堆的高度不合理,暴力往上爬是不可行的。但是如果我们放弃并查集的路径压缩,仅采用按秩合并,我们发现并查集的高度是合理的,而且形态很稳定。不妨把标记打在并查集的根上。然而合并的时候会出现问题,比如我们把u和v两个节点合并,u的size较大,一般来说我们直接让father[v]=u,size[u]+=size[v]即可,但是这样会导致u之前打的tag影响到v中的节点,所以我们做一个差分,让tag[v]-=tag[u](来自hhf的思路,%%%%)
- 全局修改:另开一个变量专门存放全局修改
- 单点查询:在并查集中暴力网上爬累加标记即可
- 联通块查询:找到堆顶即可
- 全局查询: 额外维护一个根,里面放的是所有堆的堆顶元素的值,懒的话可以像捉迷藏那样写个双堆
- 似乎还有一个问题:单点修改似乎会破坏堆的形态啊?可能并查集的根不是堆的根啊?
- 注意,在这里并查集只用来维护联通块,并且在堆顶维护可并堆的根的位置,实际形态和堆的形态没有关系
- 当然,废话了那么多都是在可并堆深度O(n)的前提下的,如果写O(log)的随机堆的话直接在堆里暴力上爬就行了
- 但为什么我棘手的操作还是只有90分啊?第三个点是什么东西啊?
- 更新:原来是合并的时候忘了维护全局答案了。。。
转载于:https://www.cnblogs.com/LoveYayoi/p/6745514.html