题目描述

在一个森林里住着N(N<=10000)只猴子。在一开始,他们是互不认识的。但是随着时间的推移,猴子们少不了争斗,但那只会发生在互不认识(认识具有传递性)的两只猴子之间。争斗时,两只猴子都会请出他认识的猴子里最强壮的一只(有可能是他自己)进行争斗。争斗后,这两只猴子就互相认识。
  每个猴子有一个强壮值,但是被请出来的那两只猴子进行争斗后,他们的强壮值都会减半(例如10会减为5,5会减为2)。
 现给出每个猴子的初始强壮值,给出M次争斗,如果争斗的两只猴子不认识,那么输出争斗后两只猴子的认识的猴子里最强壮的猴子的强壮值,否则输出 -1。

 

输入

There are several test cases, and each case consists of two parts. 

First part: The first line contains an integer N(N<=100,000), which indicates the number of monkeys. And then N lines follows. There is one number on each line, indicating the strongness value of ith monkey(<=32768). 

Second part: The first line contains an integer M(M<=100,000), which indicates there are M conflicts happened. And then M lines follows, each line of which contains two integers x and y, indicating that there is a conflict between the Xth monkey and Yth. 

 

输出

For each of the conflict, output -1 if the two monkeys know each other, otherwise output the strongness value of the strongest monkey in all friends of them after the duel.

 

样例输入

5 20 16 10 10 4 5 2 3 3 4 3 5 4 5 1 5

样例输出

8 5 5 -1 10
 
删除就是把左子树合并到右子树,然后再把根节点除以2加入右子树中
 
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<ctime>
 7 using namespace std;
 8 const int N=100005;
 9 int n;int fa[N];
10 struct node{
11     int x,dis;
12     node *l,*r;
13     int ldis(){return l?l->dis:0;}
14     int rdis(){return r?r->dis:0;}
15 }a[N];
16 int gi()
17 {
18     int str=0;char ch=getchar();
19     while(ch>'9' || ch<'0')ch=getchar();
20     while(ch>='0' && ch<='9')str=str*10+ch-'0',ch=getchar();
21     return str;
22 }
23 int find(int x){
24     return x==fa[x]?x:fa[x]=find(fa[x]);
25 }
26 node *root[N],*pos=a;
27 void newnode(node *&p,int key)
28 {
29     p=pos++;
30     p->l=p->r=NULL;
31     p->dis=0;p->x=key;
32 }
33 node *merge(node *p,node *q)
34 {
35     if(!p || !q)return p?p:q;
36     if(p->x<q->x)swap(p,q);
37     p->r=merge(p->r,q);
38     if(p->ldis()<p->rdis())swap(p->l,p->r);
39     p->dis=p->rdis()+1;
40     return p;
41 }
42 void Delet(int t)
43 {
44     node *R=root[t]->r;
45     node *L=root[t]->l;
46     node *rt=root[t];
47     rt->dis=0;rt->l=rt->r=NULL;rt->x>>=1;
48     root[t]=merge(R,L);
49     root[t]=merge(root[t],rt);
50 }
51 void work()
52 {
53     int x;
54     for(int i=1;i<=n;i++)
55     {
56         fa[i]=i;x=gi();
57         newnode(root[i],x);
58     }
59     int m=gi(),y;
60     while(m--)
61     {
62         x=gi();y=gi();
63         if(find(x)==find(y)){
64             printf("-1\n");
65             continue;
66         }
67         else{
68             int xx=find(x),yy=find(y);
69             Delet(xx);Delet(yy);
70             fa[yy]=xx;
71             root[xx]=merge(root[xx],root[yy]);
72             printf("%d\n",root[xx]->x);
73         }
74     }
75     return ;
76 }
77 int main()
78 {
79     while(~scanf("%d",&n)){
80         work();
81         pos=a;
82     }
83     return 0;
84 }