[BZOJ 1816] [Cqoi2010] 扑克牌 【二分答案】

题目链接:BZOJ - 1816

题目分析

答案具有可以二分的性质,所以可以二分答案。

验证一个答案 x 是否可行,就累加一下各种牌相对于 x 还缺少的量,如果总和超过了 x 或 m ,就不可行。

因为,当使用的joker小于等于 x 时,才可以通过合适地安排顺序使得每组牌中至多有一张 joker 。

代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>

using namespace std;

const int MaxN = 50 + 5;

int n, m, MaxA, Ans;
int A[MaxN];

bool Check(int x) {
	int t = min(x, m);
	for (int i = 1; i <= n; ++i) {
		if (A[i] < x) {
			t -= x - A[i];
			if (t < 0) return false;
		}
	}
	return true;
}

int main()
{
	scanf("%d%d", &n, &m);
	MaxA = -1;
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &A[i]);
		MaxA = max(MaxA, A[i]);
	}
	Ans = 0;
	int l, r, mid;
	l = 0; r = MaxA + m;
	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;
}

  

时间: 2024-10-28 20:10:09

[BZOJ 1816] [Cqoi2010] 扑克牌 【二分答案】的相关文章

BZOJ 1816: [Cqoi2010]扑克牌( 二分答案 )

二分答案.. 一开始二分的初始右边界太小了然后WA,最后一气之下把它改成了INF... ------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep( i , n ) for( int i = 0 ; i

bzoj1816: [Cqoi2010]扑克牌(二分答案判断)

1816: [Cqoi2010]扑克牌 题目:传送门 题解: 被一道毒瘤题搞残了...弃了坑来刷刷水题 一开始还想复杂了...结果发现二分水过: 二分答案...然后check一下,joker肯定尽量用mid次,那么哪种牌不够就补(因为每次只能补一种,所以如果次数用完就return false) 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5

[BZOJ 1816][Cqoi2010]扑克牌(二分答案)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1816 分析: 我先以为是道水题,但是要注意的是每套牌中Joker只能用1张的,所以就出现了可能目前每种牌的剩余牌数都够,但不一定不用Joker,然后就短路了…… 看了hzwer的blog顿时茅塞顿开,原来是二分…… 二分答案x,然后判定 判定的方法:注意每套牌顶多只有一个Joker,所以对于答案x,能用的Joker的最大数量是T=Min(x,m),然后枚举每种牌,将每种牌相对于答案x差的个数

bzoj 1816: [Cqoi2010]扑克牌

1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int l,r,m,n,a[60],ans; 5 bool pan(int x) 6 { 7 int a1=min(x,m); 8 for(int i=1;i<=n;i++) 9 if(a[i]<x) 10 { 11 a1-=x-a[i]; 12 if(a1<0) 13 return 0; 14 } 15 return 1; 16 }

【BZOJ1816】[Cqoi2010]扑克牌 二分

[BZOJ1816][Cqoi2010]扑克牌 Description 你有n种牌,第i种牌的数目为ci.另外有一种特殊的牌:joker,它的数目是m.你可以用每种牌各一张来组成一套牌,也可以用一张joker和除了某一种牌以外的其他牌各一张组成1套牌.比如,当n=3时,一共有4种合法的套牌:{1,2,3}, {J,2,3}, {1,J,3}, {1,2,J}. 给出n, m和ci,你的任务是组成尽量多的套牌.每张牌最多只能用在一副套牌里(可以有牌不使用). Input 第一行包含两个整数n, m

BZOJ 2280 Poi2011 Plot 二分答案+随机增量法

题目大意:给定n个点,要求分成m段,使每段最小覆盖圆半径的最大值最小 二分答案,然后验证的时候把点一个个塞进最小覆盖圆中,若半径超了就分成一块-- 等等你在跟我说不随机化的随机增量法? 好吧 那么对于一个点pos,我们要计算最大的bound满足[pos,bound]区间内的最小覆盖圆半径不超过二分的值 直接上二分是不可取的,因为我们要求m次,如果每次都验证一遍[1,n/2]直接就炸了 我们可以这么搞 首先判断[pos,pos+1-1]是否满足要求 然后判断[pos,pos+2-1]是否满足要求

BZOJ 2525 Poi2011 Dynamite 二分答案+树形贪心

题目大意:给定一棵树,有一些点是关键点,要求选择不超过m个点,使得所有关键点到最近的选择的点距离最大值最小 二分答案,问题转化为: 给定一棵树,有一些点是关键点,要求选择最少的点使得每个关键点到选择的点的距离不超过limit 然后我们贪心DFS一遍 对于以一个节点为根的子树,有三种状态: 0.这棵子树中存在一个选择的点,这个选择的点的贡献还能继续向上传递 1.这棵子树中存在一个未被覆盖的关键点,需要一些选择的点去覆盖他 2.这棵子树中既没有能继续向上传递的选择的点也不存在未覆盖的关键点 是不是少

BZOJ 4077 Wf2014 Messenger 二分答案+计算几何

题目大意:给定两条折线,Alice沿着第一条折线走,Bob沿着第二条折线走,邮递员从Alice路径上的任意一点出发,沿直线走到Bob的路径上后刚好和Bob相遇,三人的速度都是1m/s,求邮递员走的最短距离,无解输出impossible 二分答案,然后让Bob提前出发mid,然后求出Alice和Bob全程的最短距离,判断是否≤mid就行了 无解比较难办,反正我是提前判断了无解的情况 #include <cmath> #include <cstdio> #include <cst

BZOJ 2792 Poi2012 Well 二分答案

题目大意:给定一个非负整数序列A,每次操作可以选择一个数然后减掉1,要求进行不超过m次操作使得存在一个Ak=0且max{Ai?Ai+1}最小,输出这个最小值以及此时最小的k 二分答案,然后验证的时候首先让相邻的都不超过x,然后枚举哪个点应该改成0 如果某个点需要改成0,那么需要进行操作的位置是一段区间,左右端点都单调,扫两遍就行了 #include <cstdio> int main() { cout<<"BZ炸掉了代码一会再贴吧233"<<endl