fi,j=fk,j−1+(sumi−sumk)2
设 w<q ,且 q 比
则有
(fw,j−1+sum2w)−(fq,j−1+sum2q)sumw−sumq<2∗sumi
然后斜率优化
#include<iostream>
#include<cstdio>
#define pll pair<long long,long long>
using namespace std;
const int N=3005;
const long long INf=1e18;
long long f[N],sum[N];
int n,m;
pll q[N];
inline long long read()
{
long long a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline long long sqr(long long x)
{
return x*x;
}
double slop(pll x,pll y)
{
return (x.first-y.first)/(x.second-y.second);
}
int main()
{
n=read(); m=read();
for (int i=1;i<=n;i++)
sum[i]=read()+sum[i-1];
for (int i=1;i<=n;i++)
f[i]=sqr(sum[i]);
for (int j=2;j<=m;j++)
{
int t=1,w=0;
for (int i=1;i<=n;i++)
{
pll now=make_pair(f[i]+sqr(sum[i]),sum[i]);
while (t<w&&slop(now,q[w])<slop(q[w],q[w-1])) w--;
q[++w]=now;
while (t<w&&slop(q[t+1],q[t])<2*sum[i]) t++;
f[i]=sum[i]*sum[i]+q[t].first-2*q[t].second*sum[i];
}
}
cout << f[n]*m-sqr(sum[n]) << endl;
return 0;
}