题意:有一群猴子,每一只有一定的强壮值
刚开始,每个人都不认识别人
有m次争吵
若x,y争吵
如果 x认识y 输出-1
如果x不认识y 则x认识的猴子中(包括自己)当前强壮值最大的和y认识的猴子中(包括自己)当前强壮值最大的决斗
决斗完之后,决斗的两只猴子,强壮值减半(10->5,5->2) 且x认识的猴子和y认识的猴子都相互认识了 输出其中当前强壮值的最大值
多组数据
思路:左偏树
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 #define MAXN 100000+100 8 struct node 9 { 10 int num,NPL; 11 int left,right; 12 }; 13 node tree[MAXN]; 14 int n,m; 15 int f[MAXN],root[MAXN]; 16 int find(int x) 17 { 18 return f[x]==-1? x:f[x]=find(f[x]); 19 } 20 int Union(int x,int y) 21 { 22 f[find(x)]=find(y); 23 } 24 int merge(int x,int y) 25 { 26 if(x==0) return y; 27 if(y==0) return x; 28 if(tree[y].num>tree[x].num) 29 swap(x,y); 30 tree[x].right=merge(tree[x].right,y); 31 32 if(tree[tree[x].left].NPL<tree[tree[x].right].NPL) 33 swap(tree[x].left,tree[x].right); 34 35 if(tree[x].right==0) tree[x].NPL=0; 36 else 37 tree[x].NPL=tree[tree[x].right].NPL+1; 38 return x; 39 } 40 41 int solve(int x,int y) 42 { 43 if(find(x)==find(y)) return -1; 44 int root_x=root[find(x)],root_y=root[find(y)]; 45 tree[root_x].num/=2; tree[root_y].num/=2; 46 47 int tmp_x=merge(tree[root_x].left,tree[root_x].right); 48 tree[root_x].left=tree[root_x].right=tree[root_x].NPL=0; 49 tmp_x=merge(tmp_x,root_x); 50 51 int tmp_y=merge(tree[root_y].left,tree[root_y].right); 52 tree[root_y].left=tree[root_y].right=tree[root_y].NPL=0; 53 tmp_y=merge(tmp_y,root_y); 54 55 Union(x,y); 56 root[find(x)]=merge(tmp_x,tmp_y); 57 //cout<<tree[tmp_x].num<<" "<<tree[tmp_y].num<<" "<<y<<endl; 58 return tree[root[find(x)]].num; 59 } 60 61 int main() 62 { 63 int i,x,y; 64 while(scanf("%d",&n)!=EOF) 65 { 66 memset(tree,0,sizeof(tree)); 67 memset(f,0xff,sizeof(f)); 68 for(i=1;i<=n;i++) root[i]=i; 69 for(i=1;i<=n;i++) 70 scanf("%d",&tree[i].num); 71 scanf("%d",&m); 72 while(m--) 73 { 74 scanf("%d%d",&x,&y); 75 printf("%d\n",solve(x,y)); 76 } 77 } 78 return 0; 79 }