首页 > 其他分享 >洛谷 P3592

洛谷 P3592

时间:2022-10-27 07:44:05浏览次数:55  
标签:洛谷 cur val int mid P3592 print mx

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

设 \(f_{i,j,k}\) 表示区间 \([l,r]\),最小值不小于 \(k\) 的最大收益,\(cnt_{i,j}\) 表示区间穿过 \(i\),且区间的 \(c\ge j\) 的区间数量。

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

\[f_{l,r,k}=\max\limits_{l\lt p\lt r}\left\{f_{l,p-1,k}+f_{p+1,r,k}+cnt_{p,k}\times k\right\} \]

最后还要与 \(f_{l,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;
}

标签:洛谷,cur,val,int,mid,P3592,print,mx
From: https://www.cnblogs.com/Kobe303/p/16830753.html

相关文章

  • 洛谷P1021题解
    原题P1021[NOIP1999提高组]邮票面值设计思路概述题意分析给定两个整数\(N,K(N+K≤15)\),设计\(K\)种邮票面值\(\{a_1,a_2\dotsa_K\}\),并用共\(N\)张上述邮票......
  • 洛谷P1064题解
    原题P1064[NOIP2006提高组]金明的预算方案思路概述题意分析给定一个体积为\(n\)的背包和\(m\)个物品。每个物品通过\((\text{价值},\text{体积})\)的形式表......
  • 洛谷 P7003
    考虑当左端点固定时,区间的\(\&\)和至多有\(\logw\)种,因为\(1\)的数量是单调不升的。所以我们可以枚举区间左端点\(i\),然后ST表预处理区间\(\&\)和+二分求出......
  • 洛谷P2512 [HAOI2008]糖果传递
    SLOJP1117.糖果传递题目描述有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为11。输入格式小朋友个数n,下面n行ai​......
  • 洛谷 P6453
    设第\(i\)列高\(h_i\),建立序列\(h_i\)的小根笛卡尔树,然后树形DP。发现这样就将原来不规整的图形剖分成若干个矩形:我们发现,这样构成的若干个矩形正好对应小根笛卡......
  • 洛谷优秀油猴插件推荐
    前言转载自眭然的博客,有改编和新增下载链接油猴zip1.先打开edge浏览器的扩展(其他浏览器应该也可以加扩展,不过edge最好)2.打开开发者模式和允许来自其他应用商店的......
  • 洛谷 P6223
    树形DP完全不会。。首先将题目条件改一下:每个人有\(x-v_i\)块钱,要求使所有人的钱数非负的最小操作次数。注意到对于节点\(u\),在子树\(u\)内至多操作\(siz_u-1\)......
  • 洛谷 P5698 [CTSC1998]算法复杂度 题解
    前言咕了大半年,我回来了说实话当鸽子的感觉挺不错???原题链接题意给定一个伪代码,判断他总共需要进行几次操作,用多项式形式输出。题解首先,这是一道模拟题,发现性质的话比......
  • 洛谷 P3401
    甚么神仙题啊……#include<iostream>#include<vector>#include<cstdio>#include<cstring>#include<iterator>#include<utility>#defineintlonglongusin......
  • 洛谷上扒的DP练习题
    DP综述最优子结构:把原问题化到规模更小的问题后,原问题的最优解一定能从规模更小问题的最优解推出。无后效性:如果在某个阶段上过程的状态已知,则从此阶段以后过程的发展变......