• HDU1512 ZOJ2334 Monkey King 左偏树


    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - ZOJ2334

    题目传送门 - HDU1512


    题意概括

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


    题解

      左偏树大力维护。

      找根就最暴力的来。


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    const int N=100005;
    int n,m;
    int fa[N],ls[N],rs[N],npl[N],val[N];
    int getf(int k){
    	while (fa[k])
    		k=fa[k];
    	return k;
    }
    int merge(int a,int b){
    	if (!a||!b)
    		return a+b;
    	if (val[a]<val[b])
    		swap(a,b);
    	rs[a]=merge(rs[a],b);
    	fa[rs[a]]=a;
    	if (npl[rs[a]]>npl[ls[a]])
    		swap(rs[a],ls[a]);
    	npl[a]=npl[rs[a]]+1;
    	return a;
    }
    int weaken(int a){
    	fa[ls[a]]=fa[rs[a]]=0;
    	int b=merge(ls[a],rs[a]);
    	fa[a]=ls[a]=rs[a]=npl[a]=0;
    	val[a]>>=1;
    	return merge(a,b);
    } 
    int main(){
    	while (~scanf("%d",&n)){
    		for (int i=1;i<=n;i++){
    			scanf("%d",&val[i]);
    			fa[i]=ls[i]=rs[i]=npl[i]=0;
    		}
    		scanf("%d",&m);
    		while (m--){
    			int a,b;
    			scanf("%d%d",&a,&b);
    			a=getf(a),b=getf(b);
    			if (a==b){
    				puts("-1");
    				continue;
    			}
    			a=weaken(a);
    			b=weaken(b);
    			printf("%d
    ",max(val[a],val[b]));
    			merge(a,b);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    爱上你的一百个理由 (网摘)
    梦想向右,沉默向左
    明夕何夕,君已陌路。
    不肯嫁的几种男人(转)
    一剪梅
    C# preprocessor Directives
    Language
    C# Language Tour
    Web application
    Unsafe code
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/HDU1512.html
Copyright © 2020-2023  润新知