您的位置:首页 > 其它

【模板】可并堆

2016-04-30 13:03 288 查看
想学非旋转的Treap 然后看到里面提到斜堆 顺便学了学可并堆

可并堆

1.左偏树

http://hplonline20090711.blog.163.com/blog/static/121969114200961174556682/

其实他介绍了4种可并堆= =

2.斜堆

好像说是类似平衡树里的 Splay

merge(a,b) //a.val>b.val 大根堆

merge(a.r,b)

swap(a.l,a.r)

细节什么的还有一点= =

大体思想是合并a和b时 先合并a的右儿子和b 这个新堆是a的新右二子 然后交换a的左右儿子

就像Splay一样不明觉厉 均摊复杂度O(logn)

可并堆的操作 和基础的堆的操作貌似一毛钱关系都没有了呢= =



这是一个斜堆

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100005;
struct Node{
int ls,rs,val;
void clear() {ls=rs=0;}
}h
;
int fa
;
int n,m;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int merge(int x,int y){
if(x==0) return y;
if(y==0) return x;
if(h[x].val<h[y].val) swap(x,y);
fa[find(y)]=find(x);
h[x].rs=merge(h[x].rs,y);
swap(h[x].ls,h[x].rs);
return x;
}
int main(){
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) {scanf("%d",&h[i].val);fa[i]=i;}
scanf("%d",&m);
for(int i=1;i<=m;i++){
int x,y;
if(i==13){
i++;i--;
}
scanf("%d%d",&x,&y);
x=find(x);y=find(y);
//printf("%d %d\n",x,y);
if(x==y) {printf("-1\n");continue;}
h[x].val/=2;h[y].val/=2;
int rootx,rooty,root;
rootx=merge(h[x].ls,h[x].rs);fa[rootx]=rootx;
h[x].clear();fa[x]=x;
rootx=merge(rootx,x);fa[rootx]=rootx;
rooty=merge(h[y].ls,h[y].rs);fa[rooty]=rooty;
h[y].clear();fa[y]=y;
rooty=merge(rooty,y);fa[rooty]=rooty;
root=merge(rootx,rooty);fa[root]=root;
printf("%d\n",h[root].val);
//for(int j=1;j<=5;j++) printf("%d %d %d\n",j,h[j].ls,h[j].rs);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: