[Monkey King]
题目描述
在一个森林里住着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 }