2020ccpc 绵阳 D

本场的第一道签到题~
题意: 给定 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 1n105,0ai109

题解: 这种情况,只能在一次操作时对一个数进行操作,同时每次结束后选择最需要被加 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43900869/article/details/109459868