HDU 1512 Monkey King(左偏树模板题)

http://acm.hdu.edu.cn/showproblem.php?pid=1512

题意:

有n只猴子,每只猴子一开始有个力量值,并且互相不认识,现有每次有两只猴子要决斗,如果认识,就不打了,否则的话,这两只都会从它们所认识的猴子中派出一只力量值最大的猴子出来,并且这只猴子的力量值会减半,在打过之后,这两只猴子所在的集体就都认识了。

 

思路:
这是一道左偏树的模板题。

每个节点有5个值,l为左儿子节点,r为右儿子节点,fa为父亲节点(父亲节点的用法与并查集相似),val为优先级(这道题目就是大根堆),dis是距离值(在两棵树合并的时候使用,根据dis来决定左右子树是否需要对换)。

一开始每只猴子就是一棵树,每次决斗就是将两棵树进行合并。

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int maxn = 100000+5;
 5 
 6 int n, m;
 7 
 8 struct Heap
 9 {
10     int l,r,fa,val,dis;
11 }t[maxn];
12 
13 
14 int finds(int x)
15 {
16     return t[x].fa == -1? x:t[x].fa = finds(t[x].fa);
17 }
18 
19 int merge(int x, int y)
20 {
21     if(x == 0)  return y;   //如果为0的话,就说明是空子树,根节点当然就是另一节点了
22     if(y == 0)  return x;
23     if(t[y].val>t[x].val)  swap(x,y);  //始终往右子树进行插入
24     t[x].r = merge(t[x].r,y);
25     t[t[x].r].fa = x;
26     if(t[t[x].l].dis < t[t[x].r].dis) swap(t[x].l,t[x].r);   //是否需要左右子树的对换,这样是为了右子树尽量短
27     if(t[x].r == 0)  t[x].dis = 0;   //距离的重新分配
28     else t[x].dis = t[t[x].r].dis + 1;
29     return x;
30 }
31 
32 int pop(int &root)
33 {
34     int l = t[root].l;
35     int r = t[root].r;
36     t[root].l = t[root].r = t[root].dis = 0;
37     t[root].fa = -1;
38     t[l].fa = t[r].fa = -1;  //删除root根节点
39     return merge(l,r);       //这样一来相当于分裂成了两棵子树,重新进行合并,最后返回值为合并后的根节点
40 }
41 
42 int push(int x, int y)
43 {
44     return merge(x,y);
45 }
46 
47 int main()
48 {
49     //freopen("in.txt","r",stdin);
50     while(~scanf("%d",&n))
51     {
52         for(int i=1;i<=n;i++)
53         {
54             t[i].l=t[i].r=t[i].dis=0;
55             t[i].fa=-1;
56             scanf("%d",&t[i].val);
57         }
58         scanf("%d",&m);
59         while(m--)
60         {
61             int a,b;
62             scanf("%d%d",&a,&b);
63             int x=finds(a);
64             int y=finds(b);
65             if(x!=y)
66             {
67                 t[x].val/=2;
68                 int xx = push( pop(x),x);
69                 t[y].val/=2;
70                 int yy = push( pop(y),y);
71                 printf("%d\n",t[merge(xx,yy)].val);
72             }
73             else puts("-1");
74         }
75     }
76     return 0;
77 }

 

posted @ 2017-11-15 15:17  Kayden_Cheung  阅读(482)  评论(0编辑  收藏  举报
//目录