Description
Input
Output
一行一个整数表示答案。
upd: 无解输出-1。
Sample Input
Sample Input1 6 6 13 11 1 1 4 5 5 Sample Input2 11 11 29 10 9 4 11 7 3 3 3 4 5 4
Sample Output
Sample Output1 4 11 1 5 4 5 5 Sample Output2 11 10 9 4 11 7 7 4 7 4 7 4
Data Constraint
Solution
解法一:
贪心。
对于能需要提高到 L 的就提高。
对于当前不提高都已经大于 R 的,考虑减小前面的某些数,使当前状态合法,即 比R大了多少 就减去多少(记为val)。
于是记录每个数的变化量(增加量),从i-1 往前 递归,i-1减去val ,i-2再加上val....以此类推,若不能减(当减当某个位置增加量为负数)就无解,能减就减。
时间复杂度 O(理论复杂度是 但实际效果为
)。
法二:
dp。
最朴素做法:设f[ i ][ j ]表示第i个位置选了 j,转移枚举当前填x的最小花费。
记录转移过来的位置,倒退回去即可。
优化后时间
发现f[ i ]一定是 前面一段是不合法,后面一段不合法,中间一段答案递增 。
那么最小的f一定是合法区间的左端点。
那么先从前往后推出最后一个f[ n ]的合法区间的左端点,令a[ n ]等于它,再往前推,依次选取左端点即可。
时间复杂度
Code1
#include<cstdio>
#define I int
#define ll long long
#define F(i,a,b) for(I i=a;i<=b;i++)
#define N 50004
using namespace std;
I l,r,n,k,a[N],b[N],p,now;
ll ans;
void R(I &x){
x=0;I w=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=w;
}
I dg(I x,I v){
b[x]-=v;
if(b[x]<0) return 0;
if(x==1) return 1;
b[x-1]+=v;
if(a[x-2]+b[x-2]+a[x-1]+b[x-1]>r) return dg(x-2,a[x-2]+b[x-2]+a[x-1]+b[x-1]-r);
return 1;
}
I main(){
freopen("plan.in","r",stdin);
freopen("plan.out","w",stdout);
R(n),R(l),R(r);
F(i,1,n) R(a[i]);
F(i,2,n){
if(a[i]+a[i-1]+b[i-1]<l) b[i]=l-a[i]-a[i-1]-b[i-1];
if(a[i]+a[i-1]+b[i-1]>r&&!dg(i-1,a[i]+a[i-1]+b[i-1]-r)){ans=-1;break;}
}
if(ans!=-1){F(i,1,n) ans+=b[i];}
printf("%lld\n",ans);
if(ans!=-1){F(i,1,n) printf("%d ",a[i]+b[i]);}
return 0;
}
Code2(dp)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define I int
#define ll long long
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof a)
#define N 5004
using namespace std;
I l,r,n,k,a[N],g[N][N],p;
ll ans,c[N],f[N][N],inf;
void R(I &x){
x=0;I w=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=w;
}
I main(){
freopen("plan.in","r",stdin);
freopen("ans.out","w",stdout);
R(n),R(l),R(r);
F(i,1,n) R(a[i]);
mem(f,127);
ans=f[1][1];
F(i,a[1],r) f[1][i]=i-a[1];
F(i,1,n-1){
F(j,a[i],r) if(f[i][j]!=ans){
p=a[i+1]>l?r-j:l;
F(k,max(a[i+1],l-j),p){
if(f[i][j]+k-a[i+1]<f[i+1][k]) f[i+1][k]=f[i][g[i+1][k]=j]+k-a[i+1];
}
}
}
F(i,a[n],r) if(f[n][i]<ans) ans=f[n][k=i];
if(ans==f[0][0]){printf("-1\n");return 0;}
printf("%lld\n",ans);
Fd(i,n,1){
a[i]=k;
k=g[i][k];
}
F(i,1,n) printf("%d ",a[i]);
return 0;
}
Code3
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define I int
#define ll long long
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof a)
#define N 50004
using namespace std;
I l[N],r[N],n,k,a[N],p,now;
ll ans;
void R(I &x){
x=0;I w=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=w;
}
I main(){
freopen("plan.in","r",stdin);
freopen("plan.out","w",stdout);
R(n),R(l[0]),R(r[0]);
F(i,1,n) R(a[i]);
l[1]=a[1],r[1]=r[0];
F(i,2,n){
l[i]=max(a[i],l[0]-r[i-1]);
r[i]=r[0]-l[i-1];
}
Fd(i,n,1){
l[i-1]=max(l[i-1],l[0]-l[i]);
r[i-1]=min(r[i-1],r[0]-l[i]);
if(l[i]>r[i]){
printf("-1\n");return 0;
}
ans+=l[i]-a[i];
}
printf("%lld\n",ans);
F(i,1,n) printf("%d ",l[i]);
return 0;
}