题目链接: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));
    }
 }