CF1146G 题解

CF1146G 题解

给一个 DP 的做法。

题意

对长 \(n\) 的序列 \(a\),记 \(f(a)=(\sum\limits_{i=1}^na_i^2)+(\sum\limits_{i=1}^mc_i[\max\limits_{j=l_i}^{r_i}a_j>x_i])\),求 \(\max\limits_{\forall i\in[1,n],a_i\in[0,h]}f(a)\)

做法

显然需要区间 DP,设 \(f(l,r)\) 代表区间 \([l,r]\) 内的最大收益。

考虑如何处理对区间高度 \(\max\) 的限制,我们可以枚举区间内最大值,来将问题划分成一些子问题。

例如,如果我们想计算 \(f(l,r)\) 的值,我们可以枚举二元组 \((p,z)\),代表 \(\max\limits_{i=l}^ra_i=a_p=z\)

那么对所有满足 \(l\le l_i\le p\le r_i\le r,x_i<z\) 的分区限制 \(i\)\(c_i\) 的罚款是必须要付的,

而对于其他的分区限制是否需要缴纳罚款,还是暂时不能确定的,但我们可以发现,

此时对于区间 \([l,p-1]\)\([p+1,r]\),这两段区间是两个子问题,唯一的限制是最大值 \(a_p=z\) 带来的,

即要求 \(\max\limits_{i=l}^{p-1}a_i\)\(\max\limits_{i=p+1}^ra_i\) 都不超过 \(z\),那么我们可以在 DP 状态中记录 \(z\) 这一维,来处理这个限制。

即,记 \(f(l,r,z)\) 代表区间 \([l,r]\) 内,满足 \(\max\limits_{i=l}^ra_i\le z\) 的最大收益。

此时,区间 \([l,p-1]\)\([p+1,r]\) 内的最大收益,就可以用 \(\max\limits_{x\le z}f(l,p-1,x)\)\(\max\limits_{x\le z}f(p+1,r,x)\) 来表示,

我们维护 DP 数组的前缀最大值,即可做到 \(O(n^4)\) 转移。

code

#include<bits/stdc++.h>
#define ckmax(a, b) ((a) = max((a), (b)))
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
using namespace std;
int read() {/*快读*/}
const int N (55);
int n, m, h, f[N][N][N], lim[N][N][N][N];
struct Node { int l, r, x, c; } q[N];
int dp (int l, int r, int x, int res = -2e9) {
	if (x < 0 || l > r) return 0;
	if (f[l][r][x] != -1) return f[l][r][x];
	rep (p, l, r) ckmax (res, dp (l, p - 1, x) + dp (p + 1, r, x) + x * x + lim[l][r][p][x]);
	return f[l][r][x] = max (res, dp (l, r, x - 1));
}
int main() {
	n = read(), h = read(), m = read();
	rep (i, 1, m) {
		int l = read(), r = read(), x = read(), c = read();
		q[i].l = l, q[i].r = r, q[i].x = x, q[i].c = c;
	}
	rep (l, 1, n) rep (r, l, n) rep (p, l, r) rep (i, 1, m) {
		int L = q[i].l, R = q[i].r, X = q[i].x, C = q[i].c;
		if (l <= L && L <= p && p <= R && R <= r) lim[l][r][p][X + 1] -= C;
	}
	rep (l, 1, n) rep (r, l, n) rep (p, l, r) rep (x, 1, h) lim[l][r][p][x] += lim[l][r][p][x - 1];
	memset (f, -1, sizeof(f)), cout << dp (1, n, h); return 0;
}
posted @ 2022-04-15 12:36  GaryH  阅读(36)  评论(0编辑  收藏  举报