[CQOI2010]扑克牌(二分答案)

传送门

题意:你有n种牌,第i种牌的数目为ci.另外有一种特殊的牌:joker,它的数目是m个.你可以用每种牌各一张来组成一套牌,也可以用一张joker和除了某一种牌以外的其他牌各一张组成1套牌.给出n,m和ci,你的任务是组成尽量多的套牌.每张牌最多只能用在一副套牌里(可以有牌不使用).

分析:如果这道题你不能看出可以二分答案求解,那...我们直接二分套牌数量mid,然后对于每种牌的数量ci,如果ci小于mid,那么就需要mid-ci张joker牌,如果当前mid下所需要的joker牌的数量小于等于m,说明此次mid合法.

想到这一步,应该都没问题.但还有一个坑,就是每一套牌只能有一张joker牌,所以我们上述最后一步判断合法性应该是:如果当前mid下所需要的joker牌的数量小于等于min(m,mid),说明此次mid合法.

int n,m,ans;
int c[55];
bool check(int mid){
    int cnt=0,res=min(m,mid);//坑点
    for(int i=1;i<=n;i++){
		if(c[i]<mid){
	    	cnt+=mid-c[i];
	    	if(cnt>res)return 0;
		}
		else return 1;
//因为我在二分之前把c数组sort排序了一遍
//所以如果此次c[i]>mid,之后的c[i]就都大于mid了
//所以可以直接返回,节约时间
    }
    return 1;
}
int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++)c[i]=read();
    sort(c+1,c+n+1);
    int l=0,r=c[n]+m,mid;//注意一下二分边界.
    while(l<=r){
		mid=(l+r)>>1;
		if(check(mid)){
	    	ans=mid;
	    	l=mid+1;
		}
		else r=mid-1;
    }
    printf("%d\n",ans);
    return 0;
}

posted on 2019-02-12 15:07  PPXppx  阅读(207)  评论(0编辑  收藏  举报