本文主要是介绍2020CCPC 绵阳 7-4 Defuse the Bombs(二分),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题意:
每个炸弹有个倒计时,每一轮你指定一个炸弹时间加一,然后每一个炸弹时间减一,如果有炸弹时间变成负数,那么就会爆炸。
求有炸弹爆炸的最长时间。
思路:
二分会进行 m i d mid mid轮,那么每个炸弹的时间至少为 m i d − 1 mid-1 mid−1,一共会执行 m i d − 1 mid-1 mid−1次有效加时间操作(最后一次操作加时间没有意义),所以要满足 ∑ ( m i d − 1 − a [ i ] ) < m i d ∑(mid-1-a[i])<mid ∑(mid−1−a[i])<mid
至于为什么只要满足这个二分条件,就可以保证中间不会减出-1,可以参考群友的证明ORZ。
图中式子第一项的意思是,先只将前 j − 1 j-1 j−1个数都加到 k k k,也不会使得 a [ j ] a[j] a[j]变成负数。同理先只将前 j − 2 j-2 j−2个数都加到 k k k,也不会使得 a [ j − 1 ] a[j-1] a[j−1]变成负数。所以直接顺序将每个数加到 k k k,可以保证中间过程不会有数变成-1。
#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;typedef long long ll;
const int maxn = 1e5 + 7;
int a[maxn];
int n;bool check(ll mid) {ll num = 0;for(int i = 1;i <= n;i++) {num += max(0ll,mid - 1 - a[i]);}return num < mid;
}int main() {int T;scanf("%d",&T);int kase = 0;while(T--) {scanf("%d",&n);for(int i = 1;i <= n;i++) {scanf("%d",&a[i]);}ll l = 0,r = 1e10;ll ans = 0;while(l <= r) {ll mid = (l + r) >> 1;if(check(mid)) {ans = mid;l = mid + 1;} else {r = mid - 1;}}printf("Case #%d: %lld\n",++kase,ans);}return 0;
}
这篇关于2020CCPC 绵阳 7-4 Defuse the Bombs(二分)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!