二分

题意:
你有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,你的任务是组成尽量多的套牌。每张牌最多只能用在一副套牌里(可以有牌不使用)。

我不知道贪心行不行,如果有大佬知道怎么贪心,希望指点一下。

下面是二分做法:
我们想对结果进行二分,我们可以组成的套数一定是在[0,1e9) 左闭右开,我们在这个范围内进行二分搜索。
对于左端点l,右端点r,中间点mid,
如果中间点为true,即我们可以凑出mid及mid以上的套装数,那么我们让l = mid+1
否则我们让 r = mid-1
这样最后答案一定为l-1

关键是如何判断我们是否可以凑出mid或mid以上的套装数

我们想想,如果我们要凑出mid套卡组,对于卡牌a[i],a[i]<mid。
那么我们肯定要用joker代替他!如果最后我们,需要使用的joker数大于我们实际拥有的joker数
那么我们肯定不能成功凑出mid套卡组。
除此之外还有什么限定条件呢?对了,对于一套卡组我们最多只能用joker替代其中的一张,及我们
不能出现[j,j,3]的情况。那么这个限制条件如何体现呢?
我们想象假设mid = 6;a[i]=4,那么我们要使用2张joker代替他 a[j] = 3我们使用三张joker代替他。
我们这样代替吗?1代表一张卡牌
ai [ j, j, 1, 1, 1, 1]
aj [ j, j, j, 1, 1, 1]
不会的,因为这样当我们从上方去拿第一套卡组时,就有大于一张的joker了
所以我们这样放
ai [ j, j, 1, 1, 1, 1]
aj [ 1, 1, j, j, j, 1]
有没有看出什么,我们只能接着上一次的末尾放置joker
最多放置mid张joker
所以倘若我们放置的joker数大于mid的话,也依然是false

代码如下,注意细节

#include<iostream>;
#include<algorithm>;
using namespace std;
typedef long long ll;
const int max_r = 1e9 + 10;
const int max_n = 55;
int a[max_n];
int n, k;

int solve() {
    int l = 0;int r = max_r;
    while (l <= r) {
        int mid = (r + l) >> 1;
        ll cnt = 0;
        for (int i = 1;i <= n;i++)
            if (a[i] < mid)
                cnt += mid - a[i];
        if (cnt > mid || cnt > k) r = mid - 1;
        else l = mid + 1;
    }return l - 1;
}

int main() {
    ios::sync_with_stdio(0);
    cin >> n >> k;
    for (int i = 1;i <= n;i++)cin >> a[i];
    cout << solve() << endl;
}