Problem - 1622C - Codeforces
题意:
思路:
首先,观察样例可知,肯定是把原本的最小值减到某个值,然后再复制几次
复制的时候肯定是从大到小复制
那把最小值减到哪个值是不确定的,考虑枚举这个值?但是范围太大了
考虑二分答案,我们去二分操作次数,那么问题就是,在操作mid次之内,能不能使它满足条件
一共有两种操作,他们分别占多少不确定,考虑枚举操作1的次数
贡献直接计算即可
注意二分的右边界,取pre[n] - k
Code:
#include <bits/stdc++.h>
#define int long long
using i64 = long long;
using namespace std;
constexpr int N = 2e5 + 10;
constexpr int M = 2e5 + 10;
int n, k;
int a[N], pre[N];
bool check(int mid) {
for (int x = max(0ll, mid - n + 1); x <= mid; x ++) {
int res = 0;
int y = mid - x;
int mi = a[n] - x;
res += (a[n] - mi);
int sum = 0;
if (y < n) {
sum = (pre[y] - pre[0]);
}else {
sum = pre[n - 1];
}
res += sum - mi * min(y, n - 1);
if (pre[n] - res <= k) return true;
}
return false;
}
void solve() {
cin >> n >> k;
pre[0] = 0;
for (int i = 1; i <= n; i ++) {
pre[i] = 0;
cin >> a[i];
}
sort(a + 1, a + 1 + n, greater<int>());
for (int i = 1; i <= n; i ++) {
pre[i] = pre[i - 1] + a[i];
}
if (pre[n] <= k) {
cout << 0 << "\n";
return;
}
int l = 0, r = pre[n] - k;
int ans = 0;
while(l <= r) {
int mid = l + r >> 1;
if (check(mid)) {
ans = mid;
r = mid - 1;
}else {
l = mid + 1;
}
}
cout << ans << "\n";
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
std::cin >> t;
while(t --) {
solve();
}
return 0;
}