可并堆-STL-pbds详解
来源:互联网 发布:php 字符串替换 编辑:程序博客网 时间:2024/06/08 06:10
对于堆的合并,我们首先想到的是朴素的nlogn出堆之后nlogn入堆。实质上,有一种更为高效的数据结构——可并堆。即为在保证堆顶极值的前提下实现logn的时间合并两个堆。
与普通堆相比,左偏树的每个结点多了一个距离值NPL(Null Path Length)即该结点一直向右儿子走,到达空结点的距离。基于NPL,我们便可以发现,交换变得有序了:在保证了左儿子NPL大于右儿子NPL的时候,效率有所提升。
首先,如果左子树为空,那么把左右交换必然不会使右子树变高,所以效率提高。
第二,如果左子树的NPL比较小,那么交换后必然使右子树的高度变小,所以效率提高。
其他方面大体和堆相同。
然而这并不是我要说的主题,万能的C++给了我们神奇的STL,什么可并堆统统都给你封装好了吗~
实现代码如下
#include<cstdio> #include<algorithm> #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/priority_queue.hpp> //pb_ds库中的优先队列,支持合并#define LOL int, less<int>, binomial_heap_tag using namespace std; using namespace __gnu_pbds; //使其名称空间可用const int MAXN=1e5+5; __gnu_pbds::priority_queue<LOL> q1[MAXN]; //不打前面那串会和std下的优先队列混淆int n,m,x,y; int f[MAXN]; //记录是否在同一集合,并查集实现int fd(int x){ if(x==f[x]) return f[x]; else return f[x]=fd(f[x]); } int main(){ scanf("%d",&n); for(register int i=1;i<=n;++i){ scanf("%d",&x); q1[i].push(x); f[i]=i; } scanf("%d",&m); for(register int i=1;i<=m;++i){ scanf("%d%d",&x,&y); int fx=fd(x),fy=fd(y); if(fx==fy){ printf("-1\n"); continue; } int xa=q1[fx].top(); q1[fx].pop(); q1[fx].push(xa/2); int xb=q1[fy].top(); q1[fy].pop(); q1[fy].push(xb/2); q1[fy].join(q1[fx]); //合并的关键操作,join函数 f[fx]=fy; int xc=q1[fd(fx)].top(); printf("%d\n",xc); } return 0; }
阅读全文
5 0
- 可并堆-STL-pbds详解
- 左偏树/斜堆——可并堆详解
- HDU1512 可并堆
- 【模板】可并堆
- 可并堆?左偏树?
- 可并堆模板
- 可并堆
- 左偏树(可并堆)详解及有关模板
- 左偏树(可并堆)
- HDU1512 左偏树(可并堆)
- 猴子大王 可并堆
- 可并堆之左偏树
- luogu 3377 可并堆
- 【左偏树(可并堆)模板】
- 可并堆与二叉堆
- ZOJ 2334 可并堆<斜堆>
- [UOJ 111][APIO 2015]Jakarta Skyscrapers(Dijkstra+pbds堆暴力)
- 左偏树/斜堆/可并堆-洛谷P3377 【模板】左偏树(可并堆)
- 嵌入式uboot,内核启动通过nfs挂载根文件系统
- 暑假训练总结反思
- 66. Plus One
- ps流来封装h.264数据
- 可并堆-STL-pbds详解
- JavaScript-字符串转成拖峰的写法
- HIVE 统计商品访问的top10 数据不能插入的问题
- 多进程实现并发服务器
- SparkStream从kafka读取数据编码问题(Java)
- 62. Unique Paths&&63. Unique Paths II 路径
- Mybatis 3.1中 Mapper XML 文件 的学习详解
- 【Tricks】 Android 存储空间相关
- Unity 按指定路线移动