BZOJ1816

BZOJ1816
  • 题目

    BZOJ1816

  • 分析

    考虑二分。。

    发现若二分最多组成套牌数目, [ 1 , r ] [1,r] [1,r] 可以组成, [ 1 , r − 1 ] [1,r - 1] [1,r1] 也必然可以组成,显然满足单调性。

    二分套牌数目,因为要组成 m i d mid mid 数目的套牌,所以 a [ i ] a[i] a[i] 的数目都不可能比 m i d mid mid 小,如果比 m i d mid mid 小那么就要使用 j o k e r joker joker ,使用 j o k e r joker joker 的数目是 m i d − a [ i ] mid - a[i] mida[i] ,因为每套牌只能使用一张 j o k e r joker joker ,所以能使用 j o k e r joker joker 的数目是 m i n ( m , m i d ) min(m,mid) min(m,mid) ,使用了 j o k e r joker joker 后,一定能在其他牌里面凑齐 n − 1 n-1 n1个不是 j o k e r joker joker 的牌。

    证明:

      如 果 对 于 i , a [ i ] ≤ m i d   则 需 要 补 的 j o k e r 数 目 是 m i d − a [ i ] 若 其 它 n − 1 个 数 存 在 j , a [ j ] &lt; m i d − a [ i ] , 这 表 明 没 有 办 法 凑 齐 不 是 j o k e r 的 牌 , 即 : a [ i ] + a [ j ] &lt; m i d . 当 遍 历 到 j 时 , i , j 需 要 j o k e r 的 总 数 目 为 : m i d − a [ i ] + m i d − a [ j ] , 又 因 为 a [ j ] + a [ i ] &lt; m i d 所 以 : m i d − a [ i ] + m i d − a [ j ] &gt; m i d 此 时 : _ &lt; 0 就 成 判 断 不 可 能 了 。 \begin{aligned} &amp;\ 如果对于 i, a[i] \leq mid \\ &amp;\ 则需要补的joker数目是mid - a[i] \quad 若其它n - 1个数存在j,a[j] &lt; mid - a[i],这表明没有\\&amp;办法凑齐不是 joker 的牌,即:a[i] + a[j] &lt; mid.\\ &amp;当遍历到 j 时,i,j需要joker 的总数目为:mid - a[i] + mid - a[j],又因为 a[j] + a[i] &lt; mid \\ &amp; 所以:mid - a[i] + mid - a[j] &gt; mid\\ &amp; 此时:\_ &lt; 0 就成判断不可能了。 \end{aligned}  i,a[i]mid jokermida[i]n1j,a[j]<mida[i],jokera[i]+a[j]<mid.ji,jjokermida[i]+mida[j],a[j]+a[i]<midmida[i]+mida[j]>mid_<0
    或者不嫌麻烦在 a [ i ] &lt; m i d a[i] &lt; mid a[i]<mid 判断一下, n n n 的范围太小了。。。

  • 代码

    int n, m;
    int a[55];
    int solve(int mid)
    {
    	int _ = min(m, mid);
    	for (int i = 1; i <= n; i++)
        {
            if(a[i] < mid)
            {
            	_ -= (mid - a[i]);
            	if(_ < 0) return 0;
            }  
        }
        return 1;
    }
    int main ()
    {
    	//freopen("input.in", "r", stdin);
    	//freopen("test.out", "w", stdout);
    	read(n);
    	read(m);
    	for (int i = 1; i <= n; i++) read(a[i]);
    	int l = 0;
    	int r = 0;
    	for (int i = 1; i <= n; i++)
    	{
    		r = max(r, a[i]);
    	}
    	r += m + 1;
    	while (l < r)
    	{
    		int mid = (l + r + 1) >> 1;
    		if (solve(mid)) l = mid;
    		else r = mid - 1;
    	}
    	cout << l << endl;
    	return 0 ;
    }
    
  • 题型

    二分

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值