斜率优化DP,和玩具装箱很像。。。基本是裸的
注:那个Bf函数是暴力DP,可以参考一下和下面Upper函数(斜率优化DP)的共同点
#include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> #include<queue> using namespace std; int first,last,Que[30005]; long long n,m,f[3005][3005],a[3005]; void Bf(){ for(int i=1;i<=n;i++){ f[i][1]=a[i]*a[i]; for(int j=2;j<=m;j++){ f[i][j]=f[i][j-1]; for(int k=1;k<i;k++){ f[i][j]=min(f[i][j],f[k][j-1]+(a[i]-a[k])*(a[i]-a[k])); } } } printf("%lld\n",m*f[n][m]-a[n]*a[n]); } bool DelFirst(int q1,int q2,int i,int j){ return f[q1][j-1]+a[q1]*a[q1]-2ll*a[q1]*a[i]>f[q2][j-1]+a[q2]*a[q2]-2ll*a[q2]*a[i]; } bool DelLast(int q1,int q2,int i,int j){ return (f[q1][j-1]+a[q1]*a[q1]-f[q2][j-1]-a[q2]*a[q2])*(a[i]-a[q2])<(f[q2][j-1]+a[q2]*a[q2]-f[i][j-1]-a[i]*a[i])*(a[q2]-a[q1]); } void Upper(){ for(int i=1;i<=n;i++)f[i][1]=a[i]*a[i]; for(int j=2;j<=m;j++){ f[1][j]=a[1]*a[1]; first=1; last=0; Que[++last]=1; for(int i=2;i<=n;i++){ while(first<last && DelFirst(Que[first],Que[first+1],i,j))first++; f[i][j]=f[Que[first]][j-1]+(a[Que[first]]-a[i])*(a[Que[first]]-a[i]); while(first<last && DelLast(Que[last-1],Que[last],i,j))last--; Que[++last]=i; } } printf("%lld\n",m*f[n][m]-a[n]*a[n]); } int main(){ freopen("4518.in","r",stdin); freopen("4518.out","w",stdout); scanf("%lld %lld",&n,&m); for(int i=1;i<=n;i++){ long long x; scanf("%lld",&x); a[i]=a[i-1]+x; } Upper(); return 0; }