您的位置:首页 > 其它

hdu 1512 左偏树

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

#include<iostream>
#include<cstdio>
#define maxn 100001
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: