我们可以发现,如果切的位置确定,那么切的顺序是没有影响的。
因此,化无序为有序!
那么我们可以DP一下,f[I][j]表示前I个切j刀的最大值,那么转移方程显然。。f[I][j]=max(f[k][j-1]+sum[k]*(sum[I]-sum[k]))。
然后化简一下。。
过程在本子上。。就不码了QAQ。。典型的斜率优化。
APIO2014的题似乎比较良心?QAQ
注意:
尽量避免除法,化作乘法运算。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,k,l,r,now,last;
ll f[100005][2],y[100005][2],sum[100005];
int q[100005],ans[100005];
inline ll read()
{
ll 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;
}
int main()
{
n=read(); k=read();
for (int i=1;i<=n;i++) sum[i]=read()+sum[i-1],y[i][0]=(ll)sum[i]*sum[i];
for (int j=1;j<=k;j++)
{
now=j&1; last=now^1;
l=1; r=1; q[1]=j;
for (int i=j+1;i<=n;i++)
{
while (l<r&&(y[q[l]][last]-y[q[l+1]][last])>=sum[i]*(sum[q[l]]-sum[q[l+1]])) l++;
f[i][now]=f[q[l]][last]+sum[q[l]]*(sum[i]-sum[q[l]]);
y[i][now]=sum[i]*sum[i]-f[i][now];
while (l<r&&(y[q[r-1]][last]-y[q[r]][last])*(sum[q[r]]-sum[i])>=(y[q[r]][last]-y[i][last])*(sum[q[r-1]]-sum[q[r]])) r--;
q[++r]=i;
}
}
printf("%lld\n",f[n][now]);
return 0;
}