这一道题我们可以用二分答案来做
int main(){
cin>>t;
while(t--)
{
cin>>n;
for(ll i = 1; i <= n; i++)
{
cin>>a[i];
b[i] = a[i];
}
ll l = 1;
ll r = 1e9;
ll answer = 0;
while(l <= r)
{
ll mid = (l + r) >> 1;
if(check(mid))
{
answer = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
for(ll i = 1; i <= n; i++)
{
a[i] = b[i];
}
}
cout<<answer<<endl;
}
return 0;
}
中点在于如何验证check函数
我们考虑反着做
一个位置最好尽量把多余的给前面,但又不能超过原有的,把后面位置给的再给前面(因为题目里是正着做的,而我们是反着做的)。
在这个过程中,如果出现负数肯定是不行的。
最后判断前两个位置是否符合条件即可。
AC 代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll t,n;
ll a[200010];
ll b[200010];
bool check(ll x)
{
for(ll i = n; i >= 3; i--)
{
if(a[i] < x)
{
return 0;
}
d = min(a[i] - x,b[i]) / 3;
a[i - 2] += 2 * d;
a[i - 1] += d;
a[i] -= d * 3;
}
return a[1] >= x && a[2] >= x;
}
int main(){
cin>>t;
while(t--)
{
cin>>n;
for(ll i = 1; i <= n; i++)
{
cin>>a[i];
b[i] = a[i];
}
ll l = 1;
ll r = 1e9;
ll answer = 0;
while(l <= r)
{
ll mid = (l + r) >> 1;
if(check(mid))
{
answer = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
for(ll i = 1; i <= n; i++)
{
a[i] = b[i];
}
}
cout<<answer<<endl;
}
return 0;
}