hdu 1512 左偏树

来源:互联网 发布:瑞赛网络 编辑:程序博客网 时间:2024/05/21 10:40

题意大概是有n只猴子,m次矛盾,a和b产生矛盾时,如果他们不认识,就会找各自认识中最强壮的猴子打架,然后打架的猴子权值减半,这两拨猴子就互相认识了,成了一群猴子,每次求合成一群后的最大权值。

#include<iostream>#include<cstdio>#define maxn 100001using namespace std;int f[maxn];int find(int x){    int r=x;    while(f[r]!=r)r=f[r];    while(x!=r)    {        f[x]=r;        x=f[x];    }    return r;}int val[maxn],dis[maxn];int l[maxn],r[maxn];int merge(int x,int y){    if(x*y==0) return x+y;    if(val[x]<val[y]) swap(x,y);    r[x]=merge(r[x],y);    f[r[x]]=x;    if(dis[r[x]]>dis[l[x]]) swap(r[x],l[x]);    if(r[x])dis[x]=dis[r[x]]+1;    else dis[x]=0;    return x;}int del(int x){    int L=l[x],R=r[x];    f[L]=L;f[R]=R;    dis[x]=l[x]=r[x]=0;    return merge(L,R);}void solve(int x,int y){    int rx=del(x);    val[x]/=2;    x=merge(rx,x);    int ry=del(y);    val[y]/=2;    y=merge(ry,y);    printf("%d\n",val[merge(x,y)]);}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        for(int i=1;i<=n;i++)        {            f[i]=i;            dis[i]=l[i]=r[i]=0;            scanf("%d",&val[i]);        }        int m;        scanf("%d",&m);        int u,v,fu,fv;        for(int i=1;i<=m;i++)        {            scanf("%d%d",&u,&v);            int fu=find(u),fv=find(v);            if(fu!=fv)                solve(fu,fv);            else puts("-1");        }    }    return 0;}
1 0
原创粉丝点击