社区讨论

求解?!?

P3648[APIO2014] 序列分割参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@mi86bzmb
此快照首次捕获于
2025/11/21 09:20
4 个月前
此快照最后确认于
2025/11/21 09:20
4 个月前
查看原帖
!?蜜汁优化?!
大夫,还能救一下吗?
C
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 1e5 + 10, M = 210;
int n, k, ans;
int q[N], head = 1, tail = 1;
int a[N], sum[N], st;
int f[N][M], pre[N][M];
int Y(int i, int j, int m) {
	return sum[j] * sum[n] - f[j][m - 1] - sum[i] * sum[n] + sum[i] * sum[i];
}
int X(int a) {
	return sum[a];
}
int main() {
	freopen("125.txt", "r", stdin);
	scanf("%d%d", &n, &k);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		sum[i] = sum[i - 1] + a[i];
	}

	for (int m = 1; m <= k; m++) {
		head = 1, tail = 1;
		for (int i = 1; i <= n; i++) {
			while (head < tail && (Y(i, q[head + 1], m) - Y(i, q[head], m))
				<= sum[i] * (X(q[head + 1]) - X(q[head])))head++;
			int j = q[head];
			f[i][m] = f[j][m - 1] + (sum[i] - sum[j]) * (sum[n] - sum[i]);
			pre[i][m] = q[head];
			if (ans < f[i][m]) {
				ans = f[i][m];
				st = i;
			}
			while (head < tail && (Y(i, q[tail], m) - Y(i, q[tail - 1], m)) * (X(i) - X(q[tail - 1]))
				>= (Y(i, i, m) - Y(i, q[tail - 1], m)) * X(q[tail]) - X(q[tail - 1]))tail--;
			q[++tail] = i;
		}
	}
	printf("%d\n", ans);
	for (int x = st, i = k; i >= 1; --i) x = pre[x][i], printf("%d ", x);
}

//	f[i][m]=f[j][m-1]+(sum[i]-sum[j])*(sum[n]-sum[i])  状态转移方程 
//	sum[i]*sum[i]+sum[j]*sum[n]-f[j][m-1] -sum[i]*sum[n]=sum[i]*sum[j]-f[i][m];  优化方程

回复

2 条回复,欢迎继续交流。

正在加载回复...