推出公式以后就可以斜率dp优化了。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 100005;
LL t1[maxn], t2[maxn];
LL s[maxn];
LL *f, *g;
int q[maxn];
int n, m;
LL getfz(int j2, int j1)
{
return (f[j1] - s[j1] * s[j1]) - (f[j2] - s[j2] * s[j2]);
}
LL getfm(int j2, int j1)
{
return s[j1] - s[j2];
}
LL getf(int i, int j)
{
return f[j] + (s[i] - s[j]) * s[j];
}
void Dp(int x)
{
int h = 0, r = 0;
q[r++] = x-1;
for(int i = x; i <= n; i++) {
while(r - h > 1 && getfz(q[h], q[h+1]) >= -s[i] * getfm(q[h], q[h+1])) h++;
g[i] = getf(i, q[h]);
while(r - h > 1 && getfz(q[r-1], i) * getfm(q[r-2], q[r-1]) >= getfz(q[r-2], q[r-1]) * getfm(q[r-1], i)) r--;
q[r++] = i;
}
swap(f, g);
}
void work()
{
f = t1, g = t2;
for(int i = 1; i <= n; i++) {
scanf("%lld", &s[i]);
s[i] += s[i-1];
}
memset(f, 0, sizeof f);
for(int i = 1; i <= m; i++) Dp(i);
printf("%lld\n", f[n]);
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF) {
work();
}
return 0;
}