首页 > 其他分享 >LOJ3990/LG9602 IOI2023 足球场 题解 (区间DP+精简无用状态)

LOJ3990/LG9602 IOI2023 足球场 题解 (区间DP+精简无用状态)

时间:2024-01-23 15:34:31浏览次数:29  
标签:状态 int 题解 LOJ3990 IOI2023 MAXN max 区间 我们

首先考虑一个足球场长啥样才是合法的。发现一个点能只拐弯一次到达另一个点,可以分为两种情况:先左右走,再上下走 或 先上下走,后左右走。无论哪种情况,都要求我们走一步使得和目标点一个轴相同,再走一步使得另一个轴也相同,所以加入把每一行选择的格子看成一个区间(因为如果不连续显然是不合法的),我们选择的这些区间一定是互相包含的关系,且必须是一个凸的图形(即不能有工字形)。

然后我们考虑一个 \(O(n^3)\) 的做法,设 \(f(l,r,x)\) 表示考虑第 \([l,r]\) 行,选择的区间一定包含第 \(x\) 列的最大足球场大小(如下图就是一个 \(l=1,r=3,x=1\) 时的例子)。

考虑转移。我们对于每个状态 \((l,r,x)\) 维护一个列区间 \([L,R]\),代表我们选择的区间需要为 \([L,R]\) 的子区间,然后从 \((l+1,r,x)\) 与 \((l,r-1,x)\) 转移即可,这个部分是简单的。

但是我们会发现,这样的状态数是 \(O(n^3)\) 的,无法通过这道题。但是我们发现许多状态显然是无用的,如下图。

假设我们当前在蓝色状态(即 \((3,3,x)\) 状态),我们发现我们当前的状态一定不能成为答案,因为我们可以没有任何花费的(也就是在保持我们需要选择的区间 \([L,R]\) 不变的情况下)扩展到红色状态+蓝色状态(即 \((2,3,x)\) 状态)。

所以我们发现,我们可以固定 \(r\),有用的整数对 \((l,x)\) 不超过 \(O(n)\) 个(对于每一个 \(x\),我们显然会将 \(l\) 扩展到第 \(x\) 列上最靠下的一个障碍),所以我们只需要 \((r,x)\) 就可以唯一确定一个状态,这样我们的总状态数就降到了 \(O(n^2)\)。

考虑在这种情况下我们怎么进行转移,我们会发现,对于一个状态 \((r,x)\),我们要么就是从 \((r-1,x)\) 增加第 \(r\) 转移来,此时对答案的贡献就是当前这一行能够选择的最大区间长度(即区间 \([\max(L(r,x),L(r-1,x)),\min(R(r,x),R(r-1,x))]\),其中 \(L(r,x)\) 表示状态 \((r,x)\) 能选择的最左边的列,\(R(r,x)\) 以及下文的 \(U(r,x)\) (即向上)同理)。要么就是令第 \(r\) 行为最宽的一行,此时答案为 \(f(r,L(r-1,x))+(U(r,L(r-1,x))-U(r,x)) \times (\min(R(r,x),R(r-1,x))-\max(L(r,x),L(r-1,x)))\)。

最终我们会发现,所有信息的维护都可以在 \(O(1)\) 内完成,时间复杂度 \(O(n^2)\),可以通过本题。

const int MAXN = 2005;
int n, f[MAXN][MAXN], L[MAXN][MAXN], R[MAXN][MAXN], U[MAXN][MAXN], ll[MAXN][MAXN];
vector<pair<int, int>> dp[MAXN];

signed biggest_stadium(signed _, vector<vector<signed>> ___) {
	n = _;
	vector<vector<int>> a(n + 3, vector<int>(n + 3));
	for (int i = n; i >= 1; --i) {
		for (int j = n; j >= 1; --j) {
			a[i][j] = ___[i - 1][j - 1];
		}
	}
	for (int i = 1; i <= n; ++i)
		a[i][0] = a[i][n + 1] = a[0][i] = a[n + 1][i] = 1;
	for (int i = 0; i <= n + 1; ++i) {
		for (int j = 0; j <= n + 1; ++j) {
			if (a[i][j]) U[i][j] = i, L[i][j] = j;
			else U[i][j] = U[i - 1][j], L[i][j] = L[i][j - 1];
		}
	}
	for (int i = 0; i <= n + 1; ++i) {
		for (int j = n + 1; j >= 0; --j) {
			if (a[i][j]) R[i][j] = j;
			else R[i][j] = R[i][j + 1];
		}
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			if (a[i][j]) continue;
			dp[i - U[i][j]].push_back({i, j});
			ll[i][j] = i - U[i][j];
		}
	}
	int ans = 0;
	for (int len = 1; len <= n; ++len) {
		for (auto __ : dp[len]) {
			int r = __.first, x = __.second;
			if (a[r - 1][x]) {
				f[r][x] = R[r][x] - L[r][x] - 1;
				ans = max(ans, f[r][x]);
				continue;
			}
			f[r][x] = f[r - 1][x] +
				(min(R[r - 1][x], R[r][x]) - max(L[r - 1][x], L[r][x]) - 1);
			if (L[r - 1][x] > L[r][x]) {
				const auto upd = f[r][L[r - 1][x]] + 
					(U[r][L[r - 1][x]] - U[r][x]) * 
					(min(R[r - 1][x], R[r][x]) - L[r - 1][x] - 1);
				f[r][x] = max(f[r][x], upd);
			}
			if (R[r - 1][x] < R[r][x]) {
				const auto upd = f[r][R[r - 1][x]] +
					(U[r][R[r - 1][x]] - U[r][x]) *
					(R[r - 1][x] - max(L[r - 1][x], L[r][x]) - 1);
				f[r][x] = max(f[r][x], upd);
			}
			R[r][x] = min(R[r - 1][x], R[r][x]);
			L[r][x] = max(L[r - 1][x], L[r][x]);
			ans = max(ans, f[r][x]);
		}
	}
	return ans;
}

标签:状态,int,题解,LOJ3990,IOI2023,MAXN,max,区间,我们
From: https://www.cnblogs.com/XiaoQuQu/p/17982583

相关文章

  • CF327C Magic Five 题解
    CF327CMagicFive搬运工单调队列优化DP加等比数列求和首先\(5\)的倍数要求末尾是\(0\)或\(5\)所以我们只用看给定字符串的\(0\)和\(5\)就好,我们钦定他是最终的数的末尾。在他之前的选择删掉,在他之后的全部删掉,方案数就是\(2^{pow-1}\),答案累加就可以了。容易想到......
  • P2254 [NOI2005] 瑰丽华尔兹 题解
    P2254[NOI2005]瑰丽华尔兹搬运工单调队列优化DP还是先朴素,设\(f_{t\i\j\d}\)表示在第\(t\)个时刻,在\(i,j\)位置上,上一步是停留还是滑动的最大步数。这个就是四个方向随便转移。\(T_{max}=4*10^4\)这么做肯定不行。发现\(k\)很小,只有\(200\),所以不妨让\(k\)......
  • P2569 [SCOI2010] 股票交易 题解
    P2569[SCOI2010]股票交易搬运工稍微复杂一点的单调队列优化DP直接设\(f_{i\j}\)表示在第\(i\)天,手上还剩\(j\)个股票时的最大收入。容易写出状态转移方程:\(f_{i\j}=max\{f_{k\t}+(t-j)\cdotw\}\),这样不好看,我们可以拆成这样的形式:\[f_{i\j}=max\{f_{k\t}+t\cdo......
  • P4899 [IOI2018] werewolf 狼人 题解
    因为我记忆力不好,经常遇到之前做过的题一下子想不起来,所以打算基本上给每个比较有意思的题写题解,同时造福后代。这是werewolf,它是furry,很可爱题意:一张无向图,点有点权,每次询问从\(u\)到\(v\)的路径中,是否存在一条先走点权大于等于\(L\),再走点权小于等于\(R\)的路径。思路......
  • hugeの张江蔡唐氏模拟赛题解
    晚三huge不让去一机房,说便于管理,我的评价是:唐氏况且二机房没有luogu,改完题后没事干(指写不了狼人),遂写个没人看的题解。T1纯哈希,不写。T2纯tarjan,一直没学,不写。T3比较套路的双指针,赛时降智题意:给定由\(B\)和\(R\)组成的字符串,环形结构,每次可以交换相邻,问最少多少次可以......
  • 01.22 ARC170 题解慢报
    补完了,来发题解慢报。AB就不写了。CPrefixMexSequence考虑DP,\(f(i,j)\)表示前\(i\)个数,填了\(j\)个不同的数。如果\(s_{i+1}=1\)那么这位唯一确定,只需要保证\(j<m\)即可转移到\(f(i+1,j+1)\);如果\(s_{i+1}=0\)那么可以选旧的数也可以选新的数,分别转移即可。D......
  • 「Daily OI Round 1」block 题解
    设\(c_u\)表示节点\(u\)的颜色,\(f_u\)表示只考虑原树中\(u\)的子树中的点、选择点\(u\)的方案数。对于儿子\(v\),可以选择同色儿子节点,也可以跳过这个儿子节点,选择\(v\)的与\(u\)同色的儿子节点\(w\),故状态转移方程为:\[f_u=\prod[c_u=c_v]f_v+\left(\prod[c_u=c_w]......
  • CF1424M Ancient Language 题解
    1.题意描述一本字典中有\(r\)\((1\leqr\leq10^6)\)个单词,单词长度不超过$10^3$,所有字母都是小写英文字母,但字母排序不是按英文字母排序,求所有出现字母的一种排序,如果不存在,输出"IMPOSSIBLE"。2.题目分析由排序规则可知,对于字符串\(s\)和\(t\),\(s\)排在\(t\)......
  • CF618C Constellation 题解
    题意描述给定\(n\)个点(\(n\leq10^5\)),找到三个点满足这三个点不在同一直线上且三个点构成的三角形中不包含其他点,保证所有点不会在同一直线上。题目分析首先必然每一个点都可以作为一组解中的点。不妨其中一个点编号为\(1\)。找一个点作为第二个点,为了使没有点在这条边上,这......
  • CF1036F Relatively Prime Powers 题解
    题目分析对于一个不合法的数\(x(x\ge2)\),设\(x=\prodp_i^{r_i}\),令\(g=\gcd(r_1,r_2,\ldots,r_k)\),则\(x=\left(\prodp_i^{r_i/g}\right)^g\),所以\(x\)是一个正整数的\(g\)次方。所以可以枚举上文的\(g\),把每一类不合法方案排除掉,就是答案。设\(f(i)\)表示\(2\)......