可并堆(左高树、左偏树)

左偏树相对于二叉堆,其插入,弹出,合并的时间复杂度都是对数级别的。

高度优先左偏树(HBLT)

考虑一颗二叉树,将其叶子节点的子节点补全,那么原来有的节点叫做内部节点,新增加的节点叫做外部节点

令s(x)s(x)s(x),等于节点xxx到任意外部节点的最短路径的长度。外部节点的s(x)s(x)s(x)的值为000,叶子节点的值为111。其递归定义为:

s(x)=min⁡{s(L),s(R)}+1s(x) = \min\{s(L),s(R)\} + 1s(x)=min{s(L),s(R)}+1

定义一颗高度优先左偏树为,当且仅当其任意内部节点的左孩子的s(L)s(L)s(L)都大于等于右孩子的s(R)s(R)s(R)。

一颗高度优先左偏树有如下定理:

  • 以xxx为根的子树的节点数目至少为2s(x)−12^{s(x)}-12s(x)−1
  • 以xxx根的子树节点有mmm个,那么s(x)s(x)s(x)至多为log⁡2(m+1)\log_2(m+1)log2​(m+1)
  • 从xxx节点一直往右孩子走,直到外部节点的路径长度为s(x)s(x)s(x)
  • 高度优先左偏树是递归定义的,两个左右孩子仍然是高度优先左偏树

定义一颗二叉树既是高度优先左偏树,又是大根树,则称为最大HBLT。同理,如果同时是小根树,则称为最小HBLT。最大,最小队列可用最大最小HBLT表示。

插入

将一个数值插入一个左偏树中,由于一个节点也是左偏树,那么就相当于合并两个左偏树。

弹出

将根节点的两个左右子树进行合并,将合并后的根节点作为新的根节点。并删除原来的根节点。

合并

合并的过程是一直沿着两棵树的右路径进行合并。首先比较两个左偏树的根节点,选择权值大的那个作为合并后的根节点,并将另外一个左偏树和根节点的右节点进行递归合并。将合并后的右子树的根节点作为新的根节点,然后根据定义s(x)s(x)s(x)查看是否需要交换两个子树,最后更新根节点的s(x)s(x)s(x)的值。

线性初始化

如果我们依次插入新的节点,时间复杂度是O(nlog⁡n)O(n\log n)O(nlogn)的。我们建立一个队列,首先将节点大小为111的节点插入到队列中。每次从队首中选择两个左偏树进行合并。直到队列的大小为111。此时是时间复杂度是O(n)O(n)O(n)的。

重量优先左偏树(WBLT)

重量优先左偏树和高度优先左偏树的定义基本类似,其s(x)s(x)s(x)的定义为以xxx为根节点的子树的节点数。

其他操作和高度优先左偏树完全一致。

P3377

#include <bits/stdc++.h>
#define FR freopen("in.txt", "r", stdin)
#define FW freopen("out.txt", "w", stdout)using namespace std;typedef long long ll;struct Node
{int id;int val;int s;int l;int r;
} nodes[300005];int tot = 0;int createNode(int val)
{tot++;nodes[tot].id = tot;nodes[tot].s = 1;nodes[tot].val = val;return tot;
}int merge(int u, int v)
{if (u == 0)return v;if (v == 0)return u;if ((nodes[u].val == nodes[v].val && nodes[v].id < nodes[u].id) || nodes[u].val > nodes[v].val)swap(u, v);nodes[u].r = merge(nodes[u].r, v);if (nodes[nodes[u].r].s > nodes[nodes[u].l].s)swap(nodes[u].l, nodes[u].r);nodes[u].s = nodes[nodes[u].r].s + 1;return u;
}
int pre[300005];
int root[300005];
bool del[300005];int pop(int &u)
{if (u == 0)return 0;int val = nodes[u].val;del[nodes[u].id] = true;u = merge(nodes[u].l, nodes[u].r);return val;
}int find(int u)
{return pre[u] == u ? u : pre[u] = find(pre[u]);
}void unite(int u, int v)
{int ur = find(u);int vr = find(v);pre[ur] = vr;
}int main()
{int n, m;scanf("%d %d", &n, &m);for (int i = 1; i <= n; i++){int val;scanf("%d", &val);pre[i] = i;root[i] = createNode(val);}for (int i = 1; i <= m; i++){int op;scanf("%d", &op);if (op == 1){int x;int y;scanf("%d %d", &x, &y);if (del[x] || del[y])continue;int r = merge(root[find(x)], root[find(y)]);unite(x, y);root[find(x)] = r;}else if (op == 2){int x;scanf("%d", &x);if (del[x]){printf("-1\n");continue;}int r = root[find(x)];printf("%d\n", pop(r));root[find(x)] = r;}}return 0;
}

可并堆(左高树、左偏树)相关推荐

  1. 左偏树(可并堆)初步及其应用

    作者:hsez_yyh 链接:左偏树(可并堆)初步及其应用_hsez_yyh的博客-CSDN博客 来源:湖北省黄石二中信息竞赛组        著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  2. 【学习笔记】浅谈短小可爱的左偏树(可并堆)

    文章目录 左偏树 左偏树的合并(merge)操作 例题 罗马游戏 [Apio2012]dispatching [JLOI2015]城池攻占 [Baltic2004]sequence 左偏树 左偏树是一 ...

  3. 可并堆——左偏树 Leftist Heap

    今天学习了左偏树,这是一个好理解而且好写的数据结构,和二叉堆一样可以在O(1)时间内取出优先级最高的值,O(logn)时间内删除优先级最高的值,不同的是如果要合并两个堆那么二叉堆就只能跪了.而左偏树能 ...

  4. Monkey King(左偏树 可并堆)

    我们知道如果要我们给一个序列排序,按照某种大小顺序关系,我们很容易想到优先队列,的确很方便,但是优先队列也有解决不了的问题,当题目要求你把两个优先队列合并的时候,这就实现不了了 优先队列只有插入 删除 ...

  5. 【洛谷3377】 左偏树(可并堆)

    前言 其实我是不小心翻线性基的时候看见的. Solution 左偏树只会模板,挖坑待补 代码实现 #include<stdio.h> #include<stdlib.h> #i ...

  6. P3377-[模板]左偏树(可并堆)

    正题 题目链接:https://www.luogu.com.cn/problem/P3377 题目大意 开始时nnn个只有一个数的集合,要求支持 合并两个集合 查询一个集合中的最小值并删除 解题思路 ...

  7. 左式堆(左高树)实现

    左式堆是满足如下性质的二叉树(最小堆序): 要么为空树,要么根节点的左右子树均为左式堆,且根节点的关键码值小于等于左右子树所有节点的关键码值,此外左子树代表的左式堆的零路径长度大于等于右子树代表的左式 ...

  8. 《程序设计解题策略》——1.6 利用左偏树实现优先队列的合并

    本节书摘来自华章计算机<程序设计解题策略>一书中的第1章,第1.6节,作者:吴永辉 王建德 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 1.6 利用左偏树实 ...

  9. HDU1512 (左偏树)

    2.1.2 可并堆的定义 可并堆(Mergeable Heap)也是一种抽象数据类型,它除了支持优先队列的三个基本操作(Insert, Minimum, Delete-Min),还支持一个额外的操作- ...

最新文章

  1. codeblocks、wxWidgets环境配置
  2. Flink从入门到精通100篇(三)-如何利用InfluxDB+Grafana搭建Flink on YARN作业监控大屏环境
  3. 简化存货核算方法和物料分类帐对比
  4. Manacher 算法模板
  5. x86平台堆栈优化问题
  6. X 射线技术揭示芯片的秘密!
  7. python编写的购物网站_写一个购物商城的实例教程
  8. 数据结构 关键路径的个人理解
  9. css img 适配尺寸_一次解决你的图像尺寸和定位问题
  10. 第3次 实验 原码一位乘法实验
  11. qtcpsocket断开_Qt QTcpSocket 对连接服务器中断的不同情况进行判定
  12. oracle 生成拼音输入码,拼音码表的生成
  13. .NET并发编程-数据结构不可变性
  14. 计算机与音乐整合的教学设计,信息技术与学科教学整合音乐课教学设计  2010年10月  田赞禄...
  15. matlab图像去散焦,matlab为图像加运动模糊和散焦模糊
  16. 最近删除的照片在哪里?已删除照片恢复
  17. Visual Assist X 10.9 builds 2333 with patch.7z
  18. Elasticsearch:《大数据集群学习笔记与实战》之es集群(2)es基本操作
  19. CAD绘制二维码(网页版)
  20. python 恶搞(仿粽子写的)

热门文章

  1. 小程序获取城市行政区号_支付宝小程序开发——获取位置API没有城市区号的最佳处理方案...
  2. windows mobile注册表修改小全
  3. 请编写一个程序,使用字典存储学生信息,学生信息包含学号和姓名,请根据学生学号从小到大输出学生信息
  4. 3.1_28_4 JDK8新特性【Date】之ZoneId 时区信息
  5. 2017京东校招笔试题
  6. XMind8激活为Pro教程(Windows+Mac)
  7. 禁止迅雷极速版强制升级为最新迅雷版本的方法,最简单,最有效!
  8. 解决“无法获得下列许可 solidworks standard无法连接到服务器”的问题
  9. 怎样使用MindMapper中的聚焦功能
  10. win7 php7 redis扩展,win7 php5.6 redis扩展