Monkey King
题目大意:有n个猴子,一开始每个猴子只认识自己。每个猴子有一个力量值,力量值越大表示这个猴子打架越厉害。如果2个猴子不认识,他们就会找他们认识的猴子中力量最大的出来单挑,单挑不论输赢,单挑的2个猴子力量值减半,这2拨猴子就都认识了,不打不相识嘛。现在给m组询问,如果2只猴子相互认识,输出-1,否则他们各自找自己认识的最牛叉的猴子单挑,求挑完后这拨猴子力量最大值。
/* 左偏树模板题,包括合并,删除操作 */ #include<iostream> #include<cstdio> #define maxn 100010 using namespace std; int n,m; struct node{ int v,dis,l,r,f; }heap[maxn]; int find(int x){ if(x==heap[x].f)return x; return heap[x].f=find(heap[x].f); } int merge(int a,int b){//返回的是合并完之后根节点的编号 if(a==0)return b; if(b==0)return a; if(heap[a].v<heap[b].v)swap(a,b); heap[a].r=merge(heap[a].r,b); heap[heap[a].r].f=a; if(heap[heap[a].l].dis<heap[heap[a].r].dis)swap(heap[a].l,heap[a].r); if(heap[a].r==0)heap[a].dis=0; else heap[a].dis=heap[heap[a].r].dis+1; return a; } int pop(int a){ int l=heap[a].l; int r=heap[a].r; heap[l].f=l; heap[r].f=r; heap[a].l=heap[a].r=heap[a].dis=0; return merge(l,r); } void work(){ for(int i=1;i<=n;i++){ scanf("%d",&heap[i].v); heap[i].dis=heap[i].l=heap[i].r=0; heap[i].f=i;//并查集序号 } scanf("%d",&m); for(int i=1;i<=m;i++){ int a,b;scanf("%d%d",&a,&b); int aa=find(a),bb=find(b); if(aa==bb){puts("-1");continue;} heap[aa].v/=2;int u1=pop(aa);u1=merge(u1,aa);//修改权值(先删除,后加入) heap[bb].v/=2;int u2=pop(bb);u2=merge(u2,bb); printf("%d\n",heap[merge(u1,u2)].v); } } int main(){ freopen("Cola.txt","r",stdin); while(scanf("%d",&n)!=EOF)work(); return 0; }