想学非旋转的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[N];
int fa[N];
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);
}
}