题意:有n只猴子,每只猴子一开始有个力量值,并且互相不认识,现有每次有两只猴子要决斗,如果认识,就不打了,否则的话,这两只都会从它们所认识的猴子中派出一只力量值最大的猴子出来,并且这只猴子的力量值会减半,在打过之后,这两只猴子所在的集体就都认识了。
解题思路:左偏树裸题练习
#include<bits/stdc++.h>
#define N 100009
using namespace std;
int val[N],fa[N],ch[N][2],dis[N];
int inline read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int getfa(int x)
{
while(fa[x]) x=fa[x];
return x;
}
int merge(int x,int y)
{
if(x==0||y==0)
return x+y;
if(val[x]<val[y])//第二个条件是为题目特别设定的
swap(x,y);
ch[x][1]=merge(ch[x][1],y);
fa[ch[x][1]]=x;
if(dis[ch[x][0]]<dis[ch[x][1]])
swap(ch[x][0],ch[x][1]);
dis[x]=dis[ch[x][1]]+1;
return x;
}
int del(int x)
{
val[x]/=2;
fa[ch[x][0]]=fa[ch[x][1]]=dis[x]=0;
int y=merge(ch[x][0],ch[x][1]);
ch[x][0]=ch[x][1]=0;
merge(x,y);
}
int main()
{
//freopen("t.txt","r",stdin);
int n,m,a,b;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
val[i]=read();
ch[i][0]=ch[i][1]=fa[i]=dis[i]=0;
}
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&a,&b);
int fa=getfa(a),fb=getfa(b);
if(fa!=fb)
{
fa=del(fa);
fb=del(fb);
printf("%d\n",val[merge(fa,fb)]);
}else
printf("-1\n");
}
}
return 0;
}