洛谷 P1456 Monkey King(左偏树)

传送门


解题思路

更正题意:“输出决斗后他们朋友中最强壮的猴子的强壮值”指的是决斗前最强壮的猴子的决斗后的强壮值(根据样例得出)

所以这题就很板子了。

维护一个有合并、删除、单点插入的左偏树即可。

注意:

  • 多组数据的数组初始化处理。
  • 根节点猴子强壮值减半后对其结构体和fa[x]的重新初始化。

AC代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=100005;
 6 int n,m,fa[maxn],a[maxn];
 7 struct node{
 8     int ls,rs,dis;
 9 }t[maxn];
10 int find(int x){
11     return x==fa[x]?x:fa[x]=find(fa[x]);
12 }
13 void pushup(int x){
14     if(t[t[x].rs].dis>t[t[x].ls].dis) swap(t[x].rs,t[x].ls);
15     t[x].dis=t[t[x].rs].dis+1;
16 }
17 int merge(int x,int y){
18     if(!x||!y) return x|y; 
19     if(a[x]<a[y]) swap(x,y);
20     t[x].rs=merge(t[x].rs,y);
21     fa[t[x].rs]=x;
22     pushup(x);
23     return x;
24 }
25 void goout(int x){
26     fa[t[x].rs]=t[x].rs;
27     fa[t[x].ls]=t[x].ls;
28     int newtop=merge(t[x].rs,t[x].ls);
29     fa[x]=x;
30     t[x].dis=t[x].ls=t[x].rs=0;
31     a[x]/=2;
32     merge(x,newtop);
33 }
34 int main(){
35     while(scanf("%d",&n)!=EOF){
36         for(int i=1;i<=n;i++){
37             fa[i]=i;
38             t[i].dis=t[i].ls=t[i].rs=0;
39         }
40         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
41         scanf("%d",&m);
42         for(int i=1;i<=m;i++){
43             int x,y;
44             scanf("%d%d",&x,&y);
45             x=find(x);
46             y=find(y);
47             if(x==y){
48                 printf("-1\n");
49                 continue;
50             }
51             int newtop=merge(x,y);
52             goout(newtop);
53             printf("%d\n",a[newtop]);
54         }
55     }
56     return 0;
57 } 

 

posted @ 2020-11-30 14:27  尹昱钦  阅读(140)  评论(0编辑  收藏  举报