ZOJ 2334 Monkey King 可并堆左偏树
----------
int n,m; class LeftistTree{ private: int tot,v[maxn],l[maxn],r[maxn],d[maxn]; public: int merge(int x,int y){ if (!x) return y; if (!y) return x; if (v[x]<v[y]) swap(x,y); r[x]=merge(r[x],y); if (d[l[x]]<d[r[x]]) swap(l[x],r[x]); d[x]=d[r[x]]+1; return x; } int newNode(int x){ tot++; v[tot]=x; l[tot]=r[tot]=d[tot]=0; return tot; } int insert(int rt,int val){ return merge(rt,newNode(val)); } int top(int rt){ return v[rt]; } int pop(int rt){ return merge(l[rt],r[rt]); } void clear(){ tot=0; } }tr; int lp[maxn]; int pa[maxn]; void makeset(int n){ for (int i=0;i<=n;i++) pa[i]=i; } int findset(int x){ if (x!=pa[x]) pa[x]=findset(pa[x]); return pa[x]; } void unionset(int x,int y){ x=findset(x); y=findset(y); if (x!=y){ pa[x]=y; lp[y]=tr.merge(lp[x],lp[y]); } } int main(){ while (~scanf("%d",&n)){ makeset(n); tr.clear(); for (int i=1;i<=n;i++){ int v; scanf("%d",&v); lp[i]=tr.newNode(v); } scanf("%d",&m); for (int i=1;i<=m;i++){ int l,r; scanf("%d%d",&l,&r); if (findset(l)==findset(r)) printf("-1\n"); else{ int newPower,newRoot; newPower=tr.top(lp[findset(l)])/2; newRoot=tr.pop(lp[findset(l)]); lp[findset(l)]=tr.insert(newRoot,newPower); newPower=tr.top(lp[findset(r)])/2; newRoot=tr.pop(lp[findset(r)]); lp[findset(r)]=tr.insert(newRoot,newPower); unionset(l,r); printf("%d\n",tr.top(lp[findset(l)])); } } } return 0; }
----------