挺简单的一道题,不知道为什么是青的。我赛时直接写 \(n\log n\log V\) 的区区做法,直接过了,没花我几分钟。但是应该有点 Ad-hoc 的。

首先你考虑二分这个临界点 \(d\),显然最大化 \(d\) 约好。注意到最多 \(\log V\) 次(\(30\))就能保证全部数字都 \(\le d\)(每次的本质是在一列上不停砍半,移动可以当做没有,那么就是 \(\log V\) 次而不是 \(\log (nV)\) 次)。

根据这一点,我们考虑贪心去减。每次如果一个层是可能的,那么对于最高的元素,一次性减掉尽可能最多的出界元素一定优。此时有一个问题:可能会恰好出现 \(1\) 个无法消掉的元素。对于这种,我们可以考虑先把其移动走,此时就会恰好 \(=d-1\)。若之后没有办法补齐,那么移动之前也就没有办法消掉,就炸了,所以先移走这样的“凸起”是不劣的。

然后直接贪就可以了。

::::success[Code]

#define FileIO
#include
using namespace std;
#define ll long long
#define fi first
#define se second
#define il inline
bool stMem; double stT=clock();
const int N=2e5+10;
const ll P=998244353;
il ll qp(ll a,ll b=P-2){ll res=1;for(;b;b>>=1,a=(a*a)%P) if(b&1) res=(res*a)%P;return res;
}
// ---------------------------------------------------- //
int n,a[N],c[N];
il bool check(int d){for(int i=1;i<=n;++i)c[i]=a[i];for(int t=0;t<=30;++t) for(int i=1;i<=n;++i){if(c[i]>d&&c[i]>1){int dt=(c[i]-d+1)/2;c[i==n?1:i+1]+=dt;c[i]-=2*dt;}}for(int i=1;i<=n;++i) if(c[i]!=d) return 0;return 1;
}
// ---------------------------------------------------- //
il void solve(){cin>>n; ll su=0;for(int i=1;i<=n;++i) cin>>a[i], su+=a[i];ll l=0, r=1e9+1;while(l+1>T;while(T--) solve();cerr<<"\n";cerr<<"[Info] End Of Running. \n";cerr<<"       Time Used   : "<<(clock()-stT)/CLOCKS_PER_SEC*1000.00<<" ms\n";cerr<<"       Memory Used : "<<(&stMem-&edMem)/1048576.00<<" Mib\n";return 0;
}

::::