【模板】左偏树
一听左偏树这个名字就感觉左偏。。
左偏树是什么,好像就是个堆,大根堆或小根堆,可以支持合并,取堆顶元素,删除堆顶元素,插入元素的操作。
一些说明:
左偏树节点除了应有的东西,还有键值和距离,键值用于比较大小,距离是什么?
距离是这样定义的:
节点i称为外节点(external node),当且仅当节点i的左子树或右子树为空 ( left(i) = NULL或right(i) = NULL );节点i的距离(dist(i))是节点i到它的后代中,最近的外节点所经过的边数。特别的,如果节点i本身是外节点,则它的距离为0;而空节点的距离规定为-1 (dist(NULL) = -1)。一棵左偏树的距离,指的是该树根节点的距离。
额。。多看几遍才看懂。
左偏树具体有一些性质:
[性质1] 节点的键值小于或等于它的左右子节点的键值。(键值就是点权)——堆的性质
[性质2] 节点的左子节点的距离不小于右子节点的距离。——左偏
[性质3] 节点的距离等于它的右子节点的距离加1。(因为左偏,所以右儿子距离小)
[引理1] 若左偏树的距离为一定值,则节点数最少的左偏树是完全二叉树。
[定理1] 若一棵左偏树的距离为k,则这棵左偏树至少有2k+1-1个节点。
[性质4] 一棵N个节点的左偏树距离最多为ëlog(N+1)û -1。(这是什么鬼?)
根据性质就可以理解左偏树操作的具体步骤了。
合并A和B:1.如果有一个树为空就返回另一个
2.假定root(A).w < root(B).w, 否则交换A和B,把root(A)作为新树的根
3.合并right(A)和B, 继续步骤2
4.由于合并之后right(A)的距离可能会变大, 如果变大就交换right(A)和left(A)
5.由于right(A)距离改变,A的距离也会变,更新dis(A) = dis(right(A)) + 1
#include <iostream> #include <cstdio> using namespace std; int n, m; int f[100001], l[100001], r[100001], w[100001], d[100001];//f[i]表示第i个数所在堆的堆顶 bool b[100001];//表示是否被删除 //合并以 x, y 为根的堆 inline int merge(int x, int y) { if(!x || !y) return x + y; if(w[x] > w[y]) swap(x, y); r[x] = merge(r[x], y); f[r[x]] = x;//并查集 if(d[l[x]] < d[r[x]]) swap(l[x], r[x]); d[x] = d[r[x]] + 1; return x; } inline int pop(int x)//返回新合并的堆的堆顶 { int lc = l[x], rc = r[x]; f[lc] = lc; f[rc] = rc; l[x] = r[x] = d[x] = 0; return merge(lc, rc); } inline int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); } inline int top(int x)//第几个数所在堆的堆顶 { return w[x]; } int main() { int i, j, x, y, c, fx, fy; scanf("%d %d", &n, &m); for(i = 1; i <= n; i++) scanf("%d", &w[i]), f[i] = i; for(i = 1; i <= m; i++) { scanf("%d", &c); if(c == 1) { scanf("%d %d", &x, &y); if(b[x] || b[y]) continue;//如果有一个数被删除 fx = find(x); fy = find(y); if(fx == fy) continue;//在同一个堆中 merge(fx, fy);//合并 } else { scanf("%d", &x); if(b[x]) printf("-1\n"); else { fx = find(x); printf("%d\n", w[fx]); b[fx] = 1; f[fx] = pop(fx); //因为有的节点指向当前堆的堆顶,所以也得更新删除的堆顶 } } } return 0; }View Code
- 左偏树模板
- 左偏树 模板
- P3377 【模板】左偏树(可并堆)
- 左偏树,原理及模板
- 模板 可并堆【洛谷P3377】 【模板】左偏树(可并堆)
- [Luogu3377]【模板】左偏树(可并堆)
- 左偏树/斜堆/可并堆-洛谷P3377 【模板】左偏树(可并堆)
- 洛谷3377【【模板】左偏树】--左偏树&并查集
- ZOJ2334 Monkey King 【左偏树模板题】
- 左偏树模板
- 左偏树模板及题目推荐
- luoguP3377 【模板】左偏树(可并堆)
- luogu3377【模板】左偏树(可并堆)
- 算法模板——左偏树(可并堆)
- 【洛谷P3377】【模板】左偏树(可并堆)
- COGS 526 又是一道模板题——左偏树
- HDU 1512 Monkey King(左偏树模板题)
- 模板:左偏树
- 左偏树 模板
- 【洛谷】3377【模板】左偏树(可并堆)