首页 > 其他分享 >【SP21463 题解】

【SP21463 题解】

时间:2023-07-19 11:44:53浏览次数:35  
标签:std up int 题解 SP21463 back stk vector

Descirption

  • 给定 \(n\times m\) 的矩阵,求最大子矩阵的面积满足每一行每一列都构成等差数列。

Solution

我们另 \(up_{i, j}\) 表示最小的 \(k\) 满足 \((i, k), (i, k+1),\cdots, (i, j)\) 构成等差数列,可以用 \(\mathcal O(nm)\) 求出。

对于一个矩阵的左上角 \((a, b)\),右下角 \((c, d)\),\(b\sim d\) 中每一列都构成等差数列,则只需满足 \(a\sim c\) 中需要两行构成等差数列,则所有行都构成等差数列。

根据 玉蟾宫 相似的思路,做一遍单调栈。

枚举 \(i\) 表示第几行为底的,然后每个直立方图的高度为 \(up_{i, j}\),根据上面所述的性质判断 \(i\) 和 \(i-1\) 行是否为等差数列即可。

时间复杂度:\(\mathcal O(nm)\)。

参考代码:

#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n, m;
	std::cin >> n >> m;

	std::vector<std::vector<int>> a(n + 1, std::vector<int>(m + 1));
	for (int i = 1; i <= n; i ++ ) {
		for (int j = 1; j <= m; j ++ ) {
			std::cin >> a[i][j];
		}
	}
	
	std::vector<std::vector<int>> up(n + 1, std::vector<int>(m + 1));
	for (int j = 1; j <= m; j ++ ) {
		up[1][j] = 1;
		for (int i = 2; i <= n; i ++ ) {
			if (i == 2 || a[i][j] - a[i - 1][j] == a[i - 1][j] - a[i - 2][j]) {
				up[i][j] = up[i - 1][j];
			} else {
				up[i][j] = i - 1;
			}
		}
	}
	
	int ans = 0;
	for (int i = 1; i <= n; i ++ ) {
		int lst = 1;
		for (int j = 2; j <= m; j ++ ) {
			if (j != 2 && a[i][j] - a[i][j - 1] != a[i][j - 1] - a[i][j - 2]) {
				lst = j - 1;
			}
			ans = std::max(ans, j - lst + 1);
		}
		lst = 1;
		for (int j = 1; j <= m; j ++ ) {
			if (j == m || (j > 1 && (a[i][j + 1] - a[i][j] != a[i][j] - a[i][j - 1] || a[i - 1][j + 1] - a[i - 1][j] != a[i - 1][j] - a[i - 1][j - 1]))) {
				std::vector<int> stk;
				std::vector<int> l(m + 1), r(m + 1);
				for (int k = lst; k <= j; k ++ ) {
					while (stk.size() && up[i][k] >= up[i][stk.back()]) {
						stk.pop_back();
					}
					l[k] = stk.size() ? stk.back() + 1 : lst;
					stk.push_back(k);
				}

				std::vector<int>().swap(stk);
				for (int k = j; k >= lst; k -- ) {
					while (stk.size() && up[i][k] >= up[i][stk.back()]) {
						stk.pop_back();
					}
					r[k] = stk.size() ? stk.back() - 1 : j;
					stk.push_back(k);
				}

				for (int k = lst; k <= j; k ++ ) {
					ans = std::max(ans, (i - up[i][k] + 1) * (r[k] - l[k] + 1));
				}
				lst = j;
			}
		}
	}
	std::cout << ans << "\n";
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr), std::cout.tie(nullptr);

	int t;
	std::cin >> t;
	
	while (t -- ) {
		solve();
	}
	
	return 0;
}

标签:std,up,int,题解,SP21463,back,stk,vector
From: https://www.cnblogs.com/hcywoi/p/17565177.html

相关文章

  • BZOJ 1461 题解
    考虑设计一个哈希函数\(hash(x)=f(x)\timesbase^x\)。其中\(f(x)\)表示\(\sum_{j=1}^{i-1}[j<i]\)。然后类似于滑动窗口计算区间哈希值,加入一个数就计算贡献,减去一个数就计算这个数产生了贡献,两个东西都可以树状数组维护,那么愉快做完了。#include<bits/stdc++.h>#de......
  • P5494 题解
    来一发\(O(\logn)\)线性空间的解法。考虑通过只维护线段树叶子节点的虚树的方法压缩空间,考虑记录下每个节点的编号,然后通过异或完求最低位的\(1\)的方式求出LCA的深度,然后记录下LCA右端点的编号。在回收节点的时候可以释放储存右端点编号的空间,但是这里为了方便就不这样......
  • UNR #7 Day2 T1 火星式选拔题解
    放一个比赛链接先考虑打完暴力后\(k=1\)的特殊性质。当队列容量为\(1\)时,队中的人\(i\)会被第一个满足\(i\leqj\)且\(b_i\leqa_j\)的人淘汰,并且队列中的人会变成\(j\),考虑倍增加速这个过程,令\(f_{i,j}\)表示第\(i\)个人进队后淘汰过程发生\(2^j\)次后队......
  • P6684 题解
    真的卡不动了,但是我感觉我的思路还是有一些价值的,就来写一篇题解吧。考虑使用回滚莫队(不增)来维护,当区间删去一个点时相当于全局加入一条边,这个询问的本质是询问是否是二分图,所以考虑扩展值域并查集,这里使用路径压缩加按秩合并,记录下修改,在回滚时全部还原。总复杂度是\(O(n\sqr......
  • 「JOISC 2019 Day4」蛋糕拼接 3 题解
    先考虑这个式子:\(\sum_{j=1}^{M}|C_{k_{j}}-C_{k_{j+1}}|\)一定是在\(C\)有序时取到,具体证明很简单各位读者自己证明。那么现在式子变成:\(\sum{V}+2\times({C_{\max}-C_{\min}})\)这个时候一个常见的技巧是将\(C\)排序。这个时候就可以定义状态:\(dp_{i,j}=\s......
  • CF1438F 题解
    problem&blog。神秘随机题。众所周知:\((u,v)\)的LCA是所有点\(i\)中\(\operatorname{dis}(u,i)+\operatorname{dis}(v,i)+\operatorname{dis}(\text{root},i)\)最小的。对于一个点\(u\),设其有两个子树\(T_1,T_2\),它能作为LCA的方案数是\(|T_1|\times|T_2|\ti......
  • CF1769C2 Подкрутка II 题解
    看到同机房的好哥们发了贪心做法的题解,心血来潮就A了这道题写了真·dp的题解。虽然方法比老师上课讲的麻烦的多,并不是最优解,但至少是我自己思考得出的结果。题目要求输入一个原序列\(a_i\),从\(a_i\)中求得某个区间\([l,r]\)。此区间经过题面中所描述的修改操作(任何元素\(......
  • P6835 [Cnoi2020] 线形生物题解
    P6835[Cnoi2020]线形生物题解题目描述求从\(1\)到\(n+1\)的链的期望,其中有\(m\)条返祖边:\(u->v\)这条边\(u\gev\),等概率,求期望Solution这种爬楼梯的题一般求解\(E(x\rightarrowx+1)\),则最后答案为\(\sum_{i=1}^nE(i\rightarrowi+1)\)我们考虑从\(x\rightarr......
  • Building Bridges 题解
    BuildingBridges题目大意连接两根柱子\(i,j\)的代价是\((h_i-h_j)^2+\sum\limits_{k=j+1}^{i-1}w_k\),连接具有传递性,求将\(1,n\)连接的最小代价。思路分析斜率优化DP板题。设\(f_i\)表示考虑到前\(i\)根柱子并强制选择第\(i\)根柱子的最小代价,所求即\(f_n\)。......
  • [ABC310D] Peaceful Teams 题解
    PeacefulTeams题目大意将\(n\)个人分成\(T\)组,要求每组不能包含敌对的人,问有多少种分法。思路分析注意到\(n,T\)均很小,考虑爆搜。注意到直接枚举会枚举到分组顺序的全排列,所以可以强行嵌定大小关系去重。voiddfs(ints){if(s==n+1){for(inti=1;i<=t;......