[ SDOI 2016 ] 征途
题目
思路
代码
#include <iostream>
#include <cstring>
#define int long long
using namespace std;
const int N = 3010;
int n, m, f[N][N], s[N], q[N];
int K(int a, int b, int j) {
int y1 = f[a][j - 1] + s[a] * s[a], x1 = s[a];
int y2 = f[b][j - 1] + s[b] * s[b], x2 = s[b];
return (y1 - y2) / (x1 - x2);
}
signed main() {
cin >> n >> m;
for (int i = 1, t; i <= n; i++)
cin >> t, s[i] = s[i - 1] + t;
for (int i = 1; i <= n; i++) f[i][1] = s[i] * s[i];
for (int j = 2; j <= m; j++) {
int hh = 0, tt = -1;
for (int i = 1; i <= n; i++) {
while (hh + 1 <= tt && K(q[hh], q[hh + 1], j) < 2 * s[i]) hh++;
f[i][j] = f[q[hh]][j - 1] + (s[i] - s[q[hh]]) * (s[i] - s[q[hh]]);
while (hh + 1 <= tt && K(q[tt - 1], q[tt], j) > K(q[tt], i, j)) tt--;
q[++tt] = i;
}
}
cout << f[n][m] * m - s[n] * s[n] << endl;
return 0;
}