这题依旧是斜率优化DP。
首先我们可以发现,它的分割顺序对答案没有影响:
假设我们要将一块分为三部分,每部分的和分别为a,b,c
a * (b+c)+b * c=a * b+a * c+b * c
(a+b) * c+a * b=a * c+b * c+a * b
所以,我们可以按顺序分了。
DP式:
f[i]=max{f[j]+a[j] * (a[i]-a[j])}
这里的a[i]表示原a[]的前缀和
斜率优化,我们可以得出:
f[j]-a[j]2-f[k]+a[k]2/(a[k]-a[j])<a[i]
上标:
#include<cstdio>
#define db double
#define ll long long
#define N 100010
using namespace std;
int n,K,g[N],l,len,x,las;
ll f[2][N],a[N];
inline int read()
{
int x=0; char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
db solve(int x,int y) {return a[x]==a[y] ? -1e9:(db)(f[las][x]-a[x]*a[x]-f[las][y]+a[y]*a[y])/(a[y]-a[x]);}
int main()
{
// freopen("3675.in","r",stdin);
// freopen("3675.out","w",stdout);
n=read(),K=read();a[0]=0;
for (int i=1;i<=n;i++) a[i]=read()+a[i-1];
x=0,las=0;
for (int j=1;j<=K;j++)
{
l=len=0;x^=1;
for (int i=1;i<=n;i++)
{
while (l<len && solve(g[l+1],g[l])<a[i]) l++;
f[x][i]=f[las][g[l]]+a[g[l]]*(a[i]-a[g[l]]);
while (len>l && solve(g[len],g[len-1])>solve(i,g[len])) len--;
g[++len]=i;
}
las=x;
}
printf("%lld\n",f[las][n]);
return 0;
}