Problem - 1622C - Codeforces
题意:
思路:
首先,观察样例可知,肯定是把原本的最小值减到某个值,然后再复制几次
复制的时候肯定是从大到小复制
那把最小值减到哪个值是不确定的,考虑枚举这个值?但是范围太大了
考虑二分答案,我们去二分操作次数,那么问题就是,在操作mid次之内,能不能使它满足条件
一共有两种操作,他们分别占多少不确定,考虑枚举操作1的次数
贡献直接计算即可
注意二分的右边界,取pre[n] - k
Code:
#include <bits/stdc++.h>#define int long longusing 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;
}