本场的第一道签到题~
题意: 给定 n n n个数,每次可以选择一个数加 1 1 1,然后 n n n个数每个数都减 1 1 1,若存在某个数在减 1 1 1后小于 0 0 0,则停止操作,否则继续循环执行,问最多可以执行多少次加 1 1 1操作。
数据范围: 1 ≤ n ≤ 1 0 5 , 0 ≤ a i ≤ 1 0 9 1\leq n\leq 10^5, 0\leq a_i\leq 10^9 1≤n≤105,0≤ai≤109
题解: 这种情况,只能在一次操作时对一个数进行操作,同时每次结束后选择最需要被加 1 1 1的数(最靠近 0 0 0的数),所以每次操作的数都是变化的。
考虑二分答案。 c h e c k ( a n s ) check(ans) check(ans)即考虑当前 a n s ans ans是不是可以对所有小于 a n s ans ans的数都添加到 a n s ans ans即可,由于操作 a n s ans ans次,故。注意当 a i a_i ai过小时,可能会出现 c h e c k check check时负溢出,特判下就好。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
ll a[N];
int T, n;
bool ok(ll x) {
ll sur = x;
for(int i = 1; i <= n; ++i) {
if(a[i] >= x) continue;
sur -= x - a[i];
if(sur <= 0) break;
}
return sur > 0;
}
int main()
{
scanf("%d", &T);
for(int ca = 1; ca <= T; ++ca) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]), ++a[i];
ll l = 0, r = 1e18;
while(l < r) {
ll mid = l + r + 1 >> 1;
if(ok(mid)) l = mid;
else r = mid - 1;
}
printf("Case #%d: %lld\n", ca, l);
}
return 0;
}