用左偏树维护,每次操作删除两个堆顶再合并。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010;
int a[maxn],fa[maxn],lson[maxn],rson[maxn],hei[maxn],size[maxn],
n;
int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
}
int merge(int u,int v)
{
if (u*v==0) return u+v;
if (a[u]<a[v]) swap(u,v);
rson[u]=merge(rson[u],v);
if (hei[lson[u]]<hei[rson[u]]) swap(lson[u],rson[u]);
hei[u]=hei[rson[u]]+1;
return u;
}
void solve()
{
int q,u,v,x,y,r;
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
fa[i]=i;
lson[i]=rson[i]=0;
hei[i]=size[i]=1;
}
scanf("%d",&q);
while (q--)
{
scanf("%d%d",&u,&v);
if (find(u)==find(v)) printf("-1\n");
else
{
u=fa[u];
v=fa[v];
x=merge(lson[u],rson[u]);
y=merge(lson[v],rson[v]);
a[u]/=2;
a[v]/=2;
size[u]=size[v]=hei[u]=hei[v]=1;
lson[u]=lson[v]=rson[u]=rson[v]=0;
r=merge(merge(u,x),merge(v,y));
fa[u]=fa[v]=fa[r]=r;
printf("%d\n",a[r]);
}
}
}
int main()
{
while (scanf("%d",&n)==1) solve();
}