题目链接: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));
}
} 
京公网安备 11010502036488号