令b[i]=a[i]+a[i+1]b[i]=a[i]+a[i+1]b[i]=a[i]+a[i+1];操作转化为对b[1]b[1]b[1]或b[n−1]b[n-1]b[n−1]加一个数,或对bbb中相邻两个数同加一个数;最终要使所有b[i]b[i]b[i]满足L≤b[i]≤RL \leq b[i] \leq RL≤b[i]≤R.
考虑贪心,b[i]<Lb[i]<Lb[i]<L时尽可能增大变成LLL,L≤b[i]≤RL \leq b[i] \leq RL≤b[i]≤R尽可能不变大.
处理到iii时,前面的都已经合法;如果b[i+1]<Lb[i+1]<Lb[i+1]<L,则同加b[i]和b[i+1]b[i]和b[i+1]b[i]和b[i+1];然后,如果b[i−1]<Rb[i-1]<Rb[i−1]<R,则同加b[i]和b[i−1]b[i]和b[i-1]b[i]和b[i−1];最后,如果b[i+1]<Rb[i+1]<Rb[i+1]<R,则同加b[i]和b[i+1]b[i]和b[i+1]b[i]和b[i+1].对于b[1]b[1]b[1]和b[n−1]b[n-1]b[n−1],需要特殊处理.
#include<bits/stdc++.h>
#define mid ((l+r)>>1)
#define inf 1000000007
#define N 500005
using namespace std;
long long read()
{
long long x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x*f;
}
int n,m,L,R,a[N],b[N];
long long ans;
void work()
{
for(int i=1,k;i<n;i++)
{
if(b[i]>R)
{
ans=-1;
return;
}
if(b[i]>=L)continue;
if(i==1)
{
if(b[i+1]<L)
{
k=min(L-b[i],L-b[i+1]);
b[i]+=k;b[i+1]+=k;a[i+1]+=k;
ans+=k;
}
if(b[i]>=L)continue;
ans+=L-b[i];a[i]+=L-b[i];
b[i]=L;
continue;
}
if(i==n-1)
{
ans+=L-b[i];a[i+1]+=L-b[i];
b[i]=L;
continue;
}
if(b[i+1]<L)
{
k=min(L-b[i],L-b[i+1]);
b[i]+=k;b[i+1]+=k;a[i+1]+=k;
ans+=k;
if(b[i]>=L)continue;
}
if(b[i-1]<R)
{
k=min(L-b[i],R-b[i-1]);
b[i]+=k;b[i-1]+=k;a[i]+=k;
ans+=k;
if(b[i]>=L)continue;
}
if(b[i+1]<R)
{
k=min(L-b[i],R-b[i+1]);
b[i]+=k;b[i+1]+=k;a[i+1]+=k;
ans+=k;
if(b[i]>=L)continue;
}
if(b[i]<L)
{
ans=-1;return;
}
}
}
void print()
{
printf("%lld\n",ans);
if(ans==-1)return;
for(int i=1;i<=n;i++)
{
printf("%d ",a[i]);
}printf("\n");
}
int main()
{
n=read(),L=read(),R=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
b[i-1]=a[i]+a[i-1];
}
work();
print();
return 0;
}
博客围绕数组操作展开,将操作转化为对特定数组元素的加减。目标是让数组元素满足一定范围条件,采用贪心算法,在元素小于下限值时增大,在范围内则尽量不变。处理元素时,根据相邻元素情况进行同加操作,对特定元素需特殊处理。
7572

被折叠的 条评论
为什么被折叠?



