可并堆——左偏树 Leftist Heap
来源:互联网 发布:mac pages如何保存 编辑:程序博客网 时间:2024/06/06 03:06
今天学习了左偏树,这是一个好理解而且好写的数据结构,和二叉堆一样可以在O(1)时间内取出优先级最高的值,O(logn)时间内删除优先级最高的值,不同的是如果要合并两个堆那么二叉堆就只能跪了。而左偏树能在O(logn)的时间内实现两个堆的合并。
左偏树有两个重要的性质,
1、树中每个元素小于或大于其父亲节点的值(堆性质)
2、定义节点的距离为当前节点向下到叶子节点最少所需的边数,叶子节点的距离为0,空节点的距离是-1,令dist[i]表示i节点的距离,那么dist[i]=dist[right[i]]+1;dist[left[i]]>=dist[right[i]],所以左偏树的左右子树都是左偏树。
如下图就是一颗左偏树
左偏树最核心操作就是【合并】。删除最大,插入都可由合并得到
假如我们要构造最小堆
Merge(A,B)表示合并A和B
假如A或B中的一个为空返回另一棵树即可
否则,若A根节点小于B的根节点(否则把A和B交换),把A的根作为新的树的根然后Merge(right(A),B)即可
由于Merge过程中性质(2)可能被破坏,那么把左子树和右子树交换重新计算dist即可
C++ Code:
Lheap* merge(Lheap* a,Lheap *b){if(a==NULL)return b;if(b==NULL)return a;if(b->val>a->val)swap(a,b);a->r=merge(a->r,b);if(dis(a->l)<dis(a->r))swap(a->l,a->r);a->dis=dis(a->r)+1;return a;}
插入操作很简单,把插入的点看做看做一个左偏树,直接Merge即可
删除最小也很简单,先Merge(left(A),right(A)),再删除原来的根就行
查询即为根节点的值
——————————————————————————————————————————————————————————————————————————
题目:HDOJ 1512 Monkey King
题目大意:有N个数字,初始情况,每个数字单独构成一个集合,每次把X,Y所在集合的最大值除以2,然后合并X和Y所在集合,询问新集合的最大值,若XY本身就在同一集合输出-1
做法:并查集+左偏树维护即可
Code C++:
Accepted15121046MS16180K1627 BG++#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#define MAXN 100001using namespace std;struct Lheap{int val,dis;Lheap *l,*r;};Lheap* tree[MAXN];int fa[MAXN];void init(Lheap* &t,int val){t=new Lheap;t->val=val;t->l=t->r=NULL;t->dis=0;}int findset(int x){int y,root,t;y=x;while(y!=fa[y])y=fa[y];root=y;y=x;while(fa[y]!=y){t=fa[y];fa[y]=root;y=t;}return root;}int Union(int x,int y){int fx=findset(x);int fy=findset(y);if(fx==fy)return -1;fa[fx]=fy;return fy;}int dis(Lheap *a){return (a)?(a->dis):(-1);}Lheap* merge(Lheap* a,Lheap *b){if(a==NULL)return b;if(b==NULL)return a;if(b->val>a->val)swap(a,b);a->r=merge(a->r,b);if(dis(a->l)<dis(a->r))swap(a->l,a->r);a->dis=dis(a->r)+1;return a;}Lheap* delmax(Lheap *a){if(!a)return NULL;return merge(a->l,a->r);}int solve(int fx,int fy){Lheap *t1,*t2,*t3,*t4;init(t1,tree[fx]->val/2);t3=delmax(tree[fx]);t3=merge(t1,t3);init(t2,tree[fy]->val/2);t4=delmax(tree[fy]);t4=merge(t2,t4);fy=Union(fx,fy);tree[fy]=merge(t3,t4);return tree[fy]->val;}int main(){//freopen("gen.out","r",stdin);int n;while(scanf("%d",&n)!=EOF){for(int i=1;i<=n;i++){int atk;scanf("%d",&atk);fa[i]=i;init(tree[i],atk);}int que;scanf("%d",&que);while(que--){int x,y;scanf("%d%d",&x,&y);int fx=findset(x),fy=findset(y);if(fx!=fy)printf("%d\n",solve(fx,fy));else printf("-1\n");}for(int i=1;i<=n;i++)delete tree[i];}return 0;}
- 可并堆——左偏树 Leftist Heap
- 左偏树——可并堆
- 左偏树/斜堆——可并堆详解
- 斜堆——【模板】左偏树(可并堆)
- 可并堆?左偏树?
- 堆——heap
- 左偏树(可并堆)
- HDU1512 左偏树(可并堆)
- 可并堆之左偏树
- 【左偏树(可并堆)模板】
- (转载)左倾堆 (leftist heap):方法参见 Data Structures (Weiss)
- 03. 左式堆(Leftist Heap)
- STL——heap堆
- STL——堆heap
- 浅谈数据结构—堆(heap)
- 左堆(Leftist Heaps)
- 左偏树/斜堆/可并堆-洛谷P3377 【模板】左偏树(可并堆)
- 可并堆--左偏树(Bzoj1367&&Bzoj1455)
- ubuntu 13.10 搭建 嵌入式 debian 交叉编译工具
- Camera显示之Framework层设置显示窗口
- MFC笔记1:对话框学习
- 开发者在美国市场提升应用安装量的策略
- redmine通过https远程连接svn
- 可并堆——左偏树 Leftist Heap
- iMatrix平台新版本6.0.0.Dev发布了,大家快来看一看啦!
- 远程登录补丁
- wcf abc开发1
- SQL--日期函数的使用
- IOS CoreData的初始化使用
- instanceof运算符
- 极力阻挡民众攀爬
- 电脑非正常重启,eclipse里面所有的android项目全部都出现异常