• UVA 1335 Beijing Guards(二分答案)


    入口: https://cn.vjudge.net/problem/UVA-1335

    【题意】

    n个人为成一个圈,其中第i个人想要r[i]种不同的礼物,相邻的两个人可以聊天,炫耀自己的礼物。如果两个相邻的人拥有同一种礼物,则双方都会很不高兴,问最少需要多少种不同的礼物才能满足所有人的需求,假设每种礼物有无限多个

     

     

    【分析】

    [蓝书例题]

    如果n为偶数的话,ans = max{r[i] + r[i + 1] },(r[n + 1] = r[1]).
    如果n为奇数的话,上述式子就不成立了,因为n个人围成圈的话,头尾两人是相邻的,但他们都是奇数位置的人,不能满足奇数尽量取前,偶数尽量取后。所以要用到二分的方法搜索答案,但最关键的是怎么判断说一个值是否可以满足条件。
     

    最优分配方案定为已知p种礼物,第一个人取1~r1,偶数号人从小到大取,奇数号人从大到小取(满足相邻不重复),如果最后1和n满足不重复说明合理。然后判断函数用了两个数组left[i],right[i]分别表示第i个人从小到大礼物种类的个数和从大到小礼物种类的个数,最后left[n]如果等于0,那么p满足。根据单调性,二分(最小)答案。

    【代码】

    #include<cstdio>
    #include<iostream>
    #define debug(x) cerr<<#x<<" "<<x<<'
    ';
    using namespace std;
    inline int read(){
    	register char ch=getchar();register int x=0;
    	for(;ch<'0'||ch>'9';ch=getchar());
    	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
    	return x;
    }
    const int N=1e5+5;
    int n,a[N],le[N],ri[N];
    inline bool check(int now){
    	int x=a[1],y=now-a[1];
    	le[1]=x,ri[1]=0;
    	for(int i=2;i<=n;i++){
    		if(i&1){
    			ri[i]=min(y-ri[i-1],a[i]);
    			le[i]=a[i]-ri[i];
    		}
    		else{
    			le[i]=min(x-le[i-1],a[i]);
    			ri[i]=a[i]-le[i];
    		}
    	}
    	return !le[n];
    }
    int main(){
    	for(;n=read();){
    		int l=0,r=0,mid,ans=0;
    		for(int i=1;i<=n;i++) a[i]=read();a[n+1]=a[1];
    		if(n==1){printf("%d
    ",a[1]);continue;}
    		for(int i=1;i<=n;i++) l=max(l,a[i]+a[i+1]),r=max(r,a[i]*3);
    		if(n&1){
    			while(l<=r){
    				mid=l+r>>1;
    				if(check(mid)){
    					ans=mid;
    					r=mid-1;
    				}
    				else{
    					l=mid+1;
    				}
    			}
    		}
    		else{
    			ans=l;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }

     

  • 相关阅读:
    Python学习9——异常
    提取微信小游戏代码
    linux 命令记录
    cpp 线程传递参数
    c++ primer 记录1
    你不知道的js
    js中的对象 函数 原型
    C++ 获取时间
    linux 常见命令
    git 的基本命令
  • 原文地址:https://www.cnblogs.com/shenben/p/10315892.html
Copyright © 2020-2023  润新知