左偏树
左偏树能干什么?
合并堆。
解决:BZOJ1445罗马游戏、APIO2012-dispatching这样的题目
左偏树是什么?
可并堆的一种实现。
可并堆又是什么? 可并堆(Mergeable Heap)是一种抽象数据类型,它除了支持优先队列的三个基本操作(Insert, Minimum, Delete-Min),还支持一个额外的操作——合并操作。
那么——左偏树的定义:
from黄源河《左偏树的特点及其应用》
左偏树合并的过程:
补一张完整的图:
还是来自黄前辈的文章
左偏树要怎么写
板子(罗马游戏 )
#include <bits/stdc++.h> using namespace std; const int N = 1000050; int val[N], l[N], r[N], d[N], fa[N]; int x, y, n, m; char ord; // 合并以 x, y为根的堆,返回合并后的堆顶 int merge(int x, int y) { if(!x||!y) return x|y; // 键值小的作为堆顶 if (val[x] > val[y]) swap(x, y); r[x] = merge(r[x], y); // 维护左偏性质 if (d[r[x]] > d[l[x]]) swap(l[x], r[x]); // 重新计算距离 d[x] = d[r[x]] + 1; return x; } int find(int x) { if(fa[x] == x) return x; else return fa[x] = find(fa[x]); } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &val[i]); fa[i] = i; } scanf("%d", &m); for (int i = 1; i <= m; i++) { cin >> ord; if (ord == 'M') { scanf("%d%d", &x, &y); if (val[x] < 0 || val[y] < 0) continue; x = find(x), y = find(y); if (x != y) { int t = merge(x, y); fa[x] = fa[y] = t; } } else { scanf("%d", &x); if (val[x] < 0) { puts("0"); continue; } x = find(x); printf("%d\n", val[x]); val[x] = -1; fa[x] = merge(l[x], r[x]); fa[fa[x]] = fa[x]; } } return 0; }
———————————————未完待续—————————
推荐下黄前辈的论文:https://wenku.baidu.com/view/515f76e90975f46527d3e1d5.html
满堂花醉三千客,一剑霜寒十四州