2021.3.7

(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;
}
原文地址:https://www.cnblogs.com/herald/p/14494811.html