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;
}


----------

posted on 2014-01-07 22:10  电子幼体  阅读(146)  评论(0编辑  收藏  举报

导航