题目链接:https://ac.nowcoder.com/acm/contest/5675/E
题意:
从右向左将木块推动,直到不能再推木块,求所有列的max的最小值。
思路:
比较直观的是二分答案M,然后从高度M,从右往左推,模拟。
等价于求前缀平均值的最大。
实际上从左往右先把所有能推到左边的都尽量平分到到这一部分去,即前缀和sum平分。考虑到第i列可能比第i-1列小,这时候由于取平均值不会更新答案,而当i列比第i-1列大可能更新答案。
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 1e5+7; int a[MAXN]; int n; bool check(int x) { ll cnt = 0; for(int i = n; i >= 2; i--) { if(a[i] >= x) { cnt += (a[i]-x); } else { if(cnt >= (x-a[i])) { cnt -= (x-a[i]); } else { cnt = 0; } } } if(cnt + a[1] > x) { return false; } else { return true; } } int bsearch(int l, int r) { while (l < r) { int mid = l + r >> 1; if (check(mid)) r = mid; else l = mid + 1; } return l; } int main() { int t; scanf("%d",&t); while(t--) { int R=0; scanf("%d",&n); for(int i = 1; i <= n; i++){ scanf("%d",&a[i]); R = max(R, a[i]); } printf("%d\n",bsearch(1, R)); } }