(mathcal{A})
决策单调性
一:
int h = 1, t = 1;
q[1] = (Zhuan){0, 1, n};
for (int i = 1; i <= n; ++i) {
while (q[h].r < i) ++h;
q[h].l = i;
dp[i] = val(q[h].x, i);
while (val(i, q[t].l) <= val(q[t].x, q[t].l)) --t;
int l = q[t].l + 1, r = q[t].r + 1;
while (l < r) {
int mid = l + r - 1 >> 1;
if (val(i, mid) < val(q[t].x, mid))
r = mid;
else
l = mid + 1;
}
q[t].r = r - 1;
if (r <= n) q[++t] = (Zhuan){i, r, n};
}
二:
void solve(int j, int l, int r, int L, int R) {
if (l > r) return;
int mid = l + r >> 1, k;
dp[mid][j] = 1e18;
for (int i = L; i <= R; ++i) {
ll u = dp[i][j - 1] + sqr(m * c[mid] - m * c[i] - c[n]);
if (u < dp[mid][j]) {
dp[mid][j] = u;
k = i;
}
}
solve(j, l, mid - 1, L, k);
solve(j, mid + 1, r, k, R);
}
inline int main() {
n = read(), m = read();
for (int i = 1; i <= n; ++i) c[i] = c[i - 1] + read();
for (int i = 1; i <= n; ++i)
dp[i][1] = sqr(m * c[i] - c[n]);
for (int j = 2; j <= m; ++j)
solve(j, 1, n, 1, n);
cout << dp[n][m] / m << endl;
return 0;
}