斜率优化
如何压缩维数。
dp[i] = max(dp[j] + (s[i] - s[j]) * s[j])
dp[i] = max(dp[j] + s[i] * s[j] - sqr(s[j]));
如果k比j优且k>j
则有s[k] > s[j]
dp[j] + s[i] * s[j] - sqr(s[j]) < dp[k] + s[i] * s[k] - sqr(s[k])
(s[k] - s[j]) * s[i] > dp[j] - dp[k] - sqr(s[j]) + sqr(s[k])
s[i] > (dp[j] - dp[k] - sqr(s[j]) + sqr(s[k])) / (s[k] - s[j])
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100010
using namespace std;
int n, K;
int a[maxn];
long long dp[2][maxn], sqr[maxn], s[maxn];
int cur;
int q[maxn];
double slop(int k, int j){
return (double) (dp[cur][j] - dp[cur][k] - sqr[j] + sqr[k]) / (s[k] - s[j]);
}
void Transform(int x){
int l = 1, r = 0, j;
for(int i = x; i <= n; i ++){
while(l < r && slop(q[l], q[l + 1]) < s[i])
l ++;
j = q[l];
dp[cur ^ 1][i] = dp[cur][j] + s[i] * s[j] - sqr[j];
while(l < r && slop(q[r - 1], q[r]) > slop(q[r], i))
r --;
q[++ r] = i;
}
}
int main(){
scanf("%d%d", &n, &K);
int x, tot = 0;
for(int i = 1; i <= n; i ++){
scanf("%d", &x);
if(x)a[++ tot] = x;
}
n = tot;
for(int i = 1; i <= n; i ++){
s[i] = s[i - 1] + a[i];
sqr[i] = s[i] * s[i];
}
for(int i = 1; i <= K; i ++){
Transform(i);
cur ^= 1;
}
printf("%lld\n", dp[cur][n]);
return 0;
}