这个题题目中提到了尽量多张牌,触发了二分关键词。
二分就要考虑我二分什么,最开始我去二分了牌的数量,后面仔细读题发现应该是二分有多少套牌,然后去找当前的k需要的牌能不能由joker牌补充(也就是普通牌不够),因为牌的数量其实是固定的,就是找没有对应的数量的牌,不够的用joker补充,比如n=4,也就是每套四张牌,原生数量c数组,对应,如果我要组4套牌,那缺3张1,2张2,1张3,全用joker牌代替,然后去判断对应的m张够不够,以及需要的joker牌满不满足小于等于4,也就是我们二分的牌的数量,因为每套牌只能最多用1张joker 牌(也可以不用)。
#include <bits/stdc++.h>
using namespace std;
// ========== Fast IO ==========
#define FAST_IO \
ios::sync_with_stdio(false); \
cin.tie(nullptr)
// ========== 数据类型 ==========
using ll = long long;
using ull = unsigned long long;
using ld = long double;
template <class T>
using minpq = priority_queue<T, vector<T>, greater<T>>;
template <class T>
using maxpq = priority_queue<T>;
const ll INF64 = (1LL << 62);
const int INF32 = (1 << 30);
const int MOD = 1'000'000'007;
const ld EPS = 1e-12;
// 方向 (4 / 8 邻接)
int dx4[4] = {1, -1, 0, 0};
int dy4[4] = {0, 0, 1, -1};
int dx8[8] = {1, 1, 1, 0, 0, -1, -1, -1};
int dy8[8] = {1, 0, -1, 1, -1, 1, 0, -1};
// ========== 二分 ==========
template <class F>
ll first_true_ll(ll lo, ll hi, F pred)
{ // 找到最小的 x∈[lo,hi] 使 pred(x)=true
while (lo < hi)
{
ll mid = lo + (hi - lo) / 2;
if (pred(mid))
hi = mid;
else
lo = mid + 1;
}
return lo;
}
template <class F>
ll last_true_ll(ll lo, ll hi, F pred)
{ // 找到最大的 x∈[lo,hi] 使 pred(x)=true
while (lo < hi)
{
ll mid = lo + (hi - lo + 1) / 2;
if (pred(mid))
lo = mid;
else
hi = mid - 1;
}
return lo;
}
bool check(ll x, vector<int>& c, int m){
ll need = 0;
for(int i = 1; i< c.size(); i++){
need += (max(0ll, x- c[i]));
if(need > m) return false;
}
return need <= x;
}
// ========== Solve ==========
void solve()
{
int n, m;
cin >> n >> m;
vector<int> c(n+1);
ll sum = 0;
for(int i = 1; i<= n; i++) cin >> c[i],sum += c[i];
ll L = 0, R = (sum + m) / n + 1;
while(L < R){
ll mid = (L + R + 1) >> 1;
if(check(mid,c,m)) L = mid;
else R = mid - 1;
}
cout << L << "\n";
return;
}
// ========== Main ==========
int main()
{
FAST_IO;
// 重定向:
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
solve();
return 0;
}



京公网安备 11010502036488号