https://www.luogu.org/problem/P4072
是P2212(动态规划训练之十五)的提升版
全程抄袭题解
首先化简方差:

这样直接转移就是N×N×N的复杂度,也就是P2212

考虑优化

code:
#include<cstring> #include<cstdio> #include<queue> #define N 3005 #define int long long int f[N][N]; int que[N]; int sl[N]; int l[N]; int n,m; int min(int a,int b){return a<b?a:b;} double slope(int u,int j,int k){return double(f[u][j]-f[u][k]+sl[j]*sl[j]-sl[k]*sl[k])/(double)(sl[j]-sl[k]);} int main(){ scanf("%lld%lld",&n,&m); memset(f,0x3f,sizeof(f)); for(int i=1;i<=n;++i)scanf("%lld",&l[i]); for(int i=1;i<=n;++i)sl[i]=sl[i-1]+l[i]; int h,t; f[0][0]=0; for(int i=1;i<=n;i++)f[1][i]=sl[i]*sl[i]; for(int p=2;p<=m;p++){ h=1,t=0; for(int i=1;i<=n;i++) { while(h<t&&slope(p-1,que[h],que[h+1])<2*sl[i])h++; int j=que[h]; f[p][i]=f[p-1][j]+(sl[j]-sl[i])*(sl[j]-sl[i]); while(h<t&&slope(p-1,que[t-1],que[t])>slope(p-1,que[t],i))t--; que[++t]=i; } } int ans=m*f[m][n]-sl[n]*sl[n]; printf("%lld\n",ans); return 0; }