2020牛客暑期多校训练营(第十场)E.Game

2020牛客暑期多校训练营(第十场)E.Game

题目链接

题目描述

There are n columns of blocks standing in a row. The i-th column has a i a_i ai blocks in the beginning. Each block has size 1 × 1 × 1 1\times 1\times 1 1×1×1. Define (x,y) represent the block at column x and is the y-th block from bottom to top. You can perform one operation:

  • Push one block to the left, that means you choose one block which has no block at its right and make it move to the left. Because of the friction, the block above it will also move to the left, and because the blocks cannot intersect, the block at its left will move to the left either. This will cause a chain reaction. After every block moved, if some blocks hang in the air, then it will fall because of gravitation. Note that the blocks at column 1 can’t move to the left, so if a movement will cause a block at column 1 move, you can’t perform this operation.

Formally, let b i b_i bi be the number of blocks in the i-th column now, then you can choose block (x,y) that satisfy b x ≥ y b_x\geq y bxy and b x + 1 < y b_{x+1}bx+1<y (or x=n ). let l be the greatest position that satisfies 1 ≤ l < x 1\leq l1l<x and b l < y b_lbl<y, then you can perform this operation as long as l exists. Then for all blocks (i,j) that satisfy l < i ≤ x l< i\leq x l<ix and j ≥ y j\geq y jy, it moves to (i-1,j). After that, for blocks (x,y) (y>1) that there are no blocks in (x,y-1), it moves to (x,y-1). Repeat doing it until no blocks satisfy the condition.
2020牛客暑期多校训练营(第十场)E.Game_第1张图片
2020牛客暑期多校训练营(第十场)E.Game_第2张图片
2020牛客暑期多校训练营(第十场)E.Game_第3张图片

This shows an operation that pushes the block at (6,4), and the value of l is 3.
The goal of the game is to minimize the height of blocks. You need to operate any times of the operation and minimize max ⁡ i = 1 n b i \max\limits_{i=1}^n b_i i=1maxnbi, where b i b_i bi represents the number of blocks in the end. Output the minimize value.

输入描述:

The first line contains one integer T ( 1 ≤ T ≤ 100000 ) T (1\leq T\leq 100000) T(1T100000) — the number of test cases.
The first line of each test case contains only one integer n ( 1 ≤ n ≤ 1 0 5 ) n(1\leq n\leq 10^5) n(1n105) — the number of columns of blocks in the game.
The second line of each test case contains n integers a 1 , a 2 , … , a n ( 1 ≤ a i ≤ 1 0 9 ) a_1,a_2,\dots,a_n (1\leq a_i\leq 10^9) a1,a2,,an(1ai109) — the number of blocks in each column at the beginning.
The sum of n over all test cases does not exceed 2 ⋅ 1 0 5 2\cdot 10^5 2105.

输出描述:

Print T integers — for each test case output the minimum value of max ⁡ i = 1 n b i \max\limits_{i=1}^n b_i i=1maxnbi.

示例1

输入

2
4
2 3 5 6
8
2 1 1 4 4 6 2 3

输出

4
3

方法一:比赛时想了各种方法,最后还是用了暴力,我们不难发现,移动到最后图像的高度一定是从左往右递减的,于是我们就可以在遍历的过程中记录一个最大高度 m x mx mx,将所有矮的补齐到最大高度需要的方块数量为 r e s res res,如果碰到一个矮的 a [ i ] < m x a[i]a[i]<mx,则 r e s + = m x − a [ i ] res+=mx-a[i] res+=mxa[i];如果碰到一个高的 a [ i ] a[i] a[i],那么 c = a [ i ] − m x c=a[i]-mx c=a[i]mx 就是剩下能往左补的方块数量,那么首先判断 a [ i ] − m x a[i]-mx a[i]mx r e s res res 的关系,如果小于,那么这些方块显然无法将前 i i i 个方块全部补齐成 m x mx mx 高度,所以用 r e s − = c res-=c res=c 即可;如果大于等于,证明能将前 i i i 个方块全部补齐成 m x mx mx 高度,那么剩下的 c − r e s c-res cres 个方块就和 i i i 比较,即增加的高度为 ⌈ c − r e s i ⌉ \lceil\frac{c-res}{i}\rceil icres,更新 m x mx mx 即可,最后的 m x mx mx 就是最大高度,AC代码如下:

#include
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll a[N];
int main()
{
    int n,t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        ll mx=a[1],sum=a[1],res=0;
        for(int i=2;i<=n;i++){
            sum+=a[i];
            if(a[i]<=mx){
                res+=mx-a[i];
            }else{
                ll c=a[i]-mx;
                if(c>=res){
                    ll cnt=((c-res)%i==0?(c-res)/i:(c-res)/i+1);
                    mx=mx+cnt;
                    res=i*mx-sum;
                }else res-=c;
            }
        }
        printf("%lld\n",mx);
    }
	return 0;
}

方法二:赛后发现果然是水题,直接求前缀和,每次能获得的最大高度就是 s u m − 1 i + 1 \frac{sum-1}{i}+1 isum1+1,这个可能不好理解,其实就等于 ⌈ s u m i ⌉ \lceil\frac{sum}{i}\rceil isum,AC代码如下:

#include
using namespace std;
typedef long long ll;
const int N=1e5+5;
int main()
{
    int n,t;
    scanf("%d",&t);
    while(t--){
        ll mx=0,sum=0,x;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&x);
            sum+=x;
            mx=max(mx,(sum-1)/i+1);
        }
        printf("%lld\n",mx);
    }
	return 0;
}

你可能感兴趣的:(暴力,牛客,思维)