Date:2021.12.28
题意:n个元素,第i个元素可以分给第i-1个元素d,分给第i-2个元素2 * d(前提是第i个能分出3 * d),求分配若干次后n个元素中最小值最大是多少。
我们先来看下原题:
思路:二分答案,如何check?
首先,一个元素只会影响它前面的两个元素,因此我们从后往前来想,我们每次二分答案为mid,从最右面的元素开始贪心的减,即保证>=mid的前提下分出最多的给前面两个。如果遍历到任一元素<mid,则说明mid大了应该变小,并且当前mid也不合法。我们还是看下原题意,个人觉得题意不是很明确,具体来说划线处含义为:每个位置上最大可移动的数不超过“原序列中每一项的 h i h_i hi”,我一直以为 h i h_i hi是变动的因此每个位置上最大可移动的数也是变动的,所以1号样例的第一个一直是15,坑死人了。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5+10;
LL n,m,k,t;
LL a[N],b[N],c[N];
bool st[N];
bool check(LL mid)
{
for(int i=1;i<=n;i++) b[i]=a[i];
for(int i=n;i>=3;i--)
{
if(b[i]<mid) {return false;}
else
{
LL d=min(b[i]-mid,a[i])/3;
b[i-1]+=d;b[i-2]+=2*d;
}
}
if(b[2]>=mid&&b[1]>=mid) return true;
else return false;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--)
{
LL maxx=0;
cin>>n;for(int i=1;i<=n;i++) {cin>>a[i];maxx=max(maxx,a[i]);}
LL l=1,r=maxx;
while(l<r)
{
int mid=l+r+1>>1;
//cout<<mid<<' ';
if(!check(mid)) r=mid-1;
else l=mid;
}
cout<<l<<endl;
}
return 0;
}