四步套路 没有什么好说的= = 真心模版
Cost 前i个数两两相乘的和
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef int LL;
const int MAXN = 1000;
const int INF = 99999999;
LL d[MAXN+10][MAXN+10], Q[MAXN+10], Cost[MAXN+10], F, R, A[MAXN+10], S[MAXN+10];
int n, m;
int Slope_U(int i, int j, int p)
{
return d[p][i] - Cost[i] + S[i] * S[i] - (d[p][j] - Cost[j] + S[j] * S[j]);
}
int Slope_D(int i, int j, int p)
{
return S[i] - S[j];
}
int main()
{
while(scanf("%d%d", &n, &m) == 2 && n)
{
for(int i = 1; i <= n; i++) {
scanf("%d", &A[i]);
S[i] = S[i-1] + A[i];
}
memset(Cost, 0, sizeof(Cost));
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++)
Cost[j] += A[i] * A[j];
for(int i = 1; i <= n; i++) Cost[i] += Cost[i-1];
for(int i = 1; i <= n; i++) d[0][i] = Cost[i];
for(int j = 1; j <= m; j++)
{
F = R = 0;
Q[R++] = 0;
for(int i = 1; i <= n; i++)
{
while(F < R-1 && Slope_U(Q[F+1], Q[F], j-1) <= Slope_D(Q[F+1], Q[F], j-1) * S[i])
F++;
d[j][i] = d[j-1][Q[F]] + Cost[i] - Cost[Q[F]] - S[i] * S[Q[F]] + S[Q[F]] * S[Q[F]];
while(F < R-1 && Slope_U(Q[R-1], Q[R-2], j-1) * Slope_D(i, Q[R-1], j-1) >= Slope_U(i, Q[R-1], j-1) * Slope_D(Q[R-1], Q[R-2], j-1))
R--;
Q[R++] = i;
}
}
printf("%d\n", d[m][n]);
}
}