洛谷 P3592

首先不难发现最终答案中只会出现 ci 中的数,所以可以将 ci 离散化。

fi,j,k 表示区间 [l,r],最小值不小于 k 的最大收益,cnti,j 表示区间穿过 i,且区间的 cj 的区间数量。

枚举最小的位置 p,则有转移:

fl,r,k=maxl<p<r{fl,p1,k+fp+1,r,k+cntp,k×k}

最后还要与 fl,r,k+1 取个 max

在 DP 过程中顺便记录决策点,然后 DFS 输出。

Code:

#include <bits/stdc++.h>
using namespace std;
const int N = 55, M = 4005;
int n, m;
int L[M], R[M], c[M], _[M], tot;
int f[N][N][M], val[N][N][M], pos[N][N][M];
int cnt[N][M];
int ans[N];

void print(int l, int r, int cur) {
	if (l > r) return;
	int mid = pos[l][r][cur = val[l][r][cur]];
	ans[mid] = _[cur];
	print(l, mid - 1, cur), print(mid + 1, r, cur);
}

void init(int l, int r) {
	for (int i = l; i <= r; ++i)
		for (int j = 1; j <= tot; ++j) cnt[i][j] = 0;
	for (int i = 1; i <= m; ++i)
		if (l <= L[i] && R[i] <= r)
			for (int j = L[i]; j <= R[i]; ++j)
				++cnt[j][c[i]];
	for (int i = l; i <= r; ++i)
		for (int j = tot - 1; j; --j) cnt[i][j] += cnt[i][j + 1];
}

void dp(int l, int r) {
	for (int k = tot; k; --k) {
		int mx = 0;
		for (int p = l; p <= r; ++p) {
			int tmp = f[l][p - 1][k] + f[p + 1][r][k] + cnt[p][k] * _[k];
			if (tmp >= mx) mx = tmp, pos[l][r][k] = p;
		}
		if (mx >= f[l][r][k + 1]) f[l][r][k] = mx, val[l][r][k] = k;
		else f[l][r][k] = f[l][r][k + 1], val[l][r][k] = val[l][r][k + 1];
	}
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; ++i) scanf("%d%d%d", &L[i], &R[i], &c[i]), _[++tot] = c[i];
	sort(_ + 1, _ + tot + 1), tot = unique(_ + 1, _ + tot + 1) - (_ + 1);
	for (int i = 1; i <= m; ++i) c[i] = lower_bound(_ + 1, _ + tot + 1, c[i]) - _;
	for (int len = 1; len <= n; ++len)
		for (int l = 1; l <= n; ++l) {
			int r = l + len - 1;
			if (r > n) break;
			init(l, r), dp(l, r);
		}
	print(1, n, 1);
	printf("%d\n", f[1][n][1]);
	for (int i = 1; i <= n; ++i) printf("%d ", ans[i]);
	return 0;
}
posted @   Kobe303  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示