左偏树/可并堆
概述
左偏树就是支持实现堆的合并的数据结构。它同时满足“左偏”和“堆”的性质。
我们定义 \(dis[u] = min(dis[lson[u]], dis[rson[u]])+1\) ,其中空节点 dis 为 0。
那么:
- 左偏:对于任意节点 u,满足 \(dis[rson[u]] \leq dis[lson[u]]\),那么显然 \(dis[u] = dis[rson[u]] + 1\)。
- 堆:\(\forall u, val[u] \leq val[lson[u]], val[u] \leq val[rson[u]\)(小根堆),大根堆同理。
实现
为什么左偏树合并是\(log\) \(n\) 的呢?以小根堆为例:在我们合并两个堆的时候,显然是值较小的那一个堆的堆顶元素会作为新堆的堆顶元素。那么我们就把较小的作为堆顶,然后把另一个堆跟堆顶的右儿子进行合并。合并的过程是递归的,可以证明时间复杂度是 \(O(log\) \(n)\)。
代码片段:
if(!p || !q) return p + q;
if(val[p] > val[q] || (val[p] == val[q] && p > q)) Swap(p, q);
rson[p] = Merge(rson[p], q);
if(dis[lson[p]] < dis[rson[p]]) Swap(lson[p], rson[p]);
dis[p] = dis[rson[p]] + 1;
return p;
删除堆顶元素只需合并根节点的左右两个儿子即可。
合并后每个元素在哪个堆可以用并查集实现。要路径压缩。
全部代码(Luogu P3377):
#include <cstdio>
#define Maxn 100000
using namespace std;
int n, m, root[Maxn + 9], tot, dis[Maxn + 9], lson[Maxn + 9], rson[Maxn + 9], val[Maxn + 9];
bool killed[Maxn + 9];
int read() {
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
return x * f;
}
int Find(int x) {return root[x] == x ? root[x] : root[x] = Find(root[x]);}
void Swap(int &x, int &y) {int t = x; x = y, y = t;}
int Merge(int p, int q) {
if(!p || !q) return p + q;
if(val[p] > val[q] || (val[p] == val[q] && p > q)) Swap(p, q);
rson[p] = Merge(rson[p], q);
if(dis[lson[p]] < dis[rson[p]]) Swap(lson[p], rson[p]);
dis[p] = dis[rson[p]] + 1;
return p;
}
int main() {
n = read(), m = read();
for(int i = 1; i <= n; ++ i) val[i] = read(), root[i] = i, dis[i] = 1;
while(m --) {
int opt = read();
if(opt == 1) {
int x = read(), y = read();
if(killed[x] || killed[y]) continue;
int rtx = Find(x), rty = Find(y);
if(rtx == rty) continue;
root[rtx] = root[rty] = Merge(root[rtx], root[rty]);
}
else {
int x = read();
if(killed[x]) {puts("-1"); continue;}
int rtx = Find(x);
printf("%d\n", val[rtx]);
killed[rtx] = 1;
root[rtx] = root[lson[rtx]] = root[rson[rtx]] = Merge(lson[rtx], rson[rtx]);
}
}
return 0;
}
End
本文作者:TuSalcc
本文链接:https://www.cnblogs.com/TS357051/p/17783592.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步