题目链接
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:
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 bx≥y and b x + 1 < y b_{x+1}
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(1≤T≤100000) — 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(1≤n≤105) — 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(1≤ai≤109) — 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 2⋅105.
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.
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]
#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 isum−1+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;
}