2019牛客暑期多校训练营(第二场) H-Second Large Rectangle(单调栈)
题意:给出由01组成的矩阵,求求全是1的次大子矩阵。
思路:
单调栈
全是1的最大子矩阵的变形,不能直接把所有的面积存起来然后排序取第二大的,因为次大子矩阵可能在最大子矩阵里面,比如:
1 | 0 | 0 |
1 | 1 | 1 |
1 | 1 | 1 |
有篇博主的代码细节处理的很好,由于矩阵每行的长度一致,则不必重复在数组末尾标记0;然后由于j是从1,最开始如果push进0的话,有两个好处:
1.可以不受栈之前“残留”的元素m+1的影响
2.不用再判断栈是某为空来确定wid的值
Code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 7; int n, m, ans;
string str[N];
int h[N], mx1, mx2;
stack <int> s; void solve(int x)
{
if(x > mx1)
mx2 = mx1, mx1 = x;
else if(x > mx2) mx2 = x;
}
int main()
{
scanf("%d%d",&n, &m);
for(int i = 1; i <= n; i++) {
cin >> str[i];
for(int j = 1; j <= m; j++) {
if(str[i][j-1] == '1') h[j] += 1;
else h[j] = 0;
}
s.push(0);
for(int j = 1; j <= m + 1; j++) {
while(h[j] < h[s.top()]) {
int index = s.top(); s.pop();
int x = j - 1 - s.top(), y = h[index];
solve(x * y);
solve((x - 1)* y);
solve(x * (y - 1));
}
s.push(j);
}
}
cout << mx2 << endl;
}
悬线法
通过悬线法,可以找到以点(i,j)为底的极大矩形。
u[i][j]、l[i][j]、r[i][j]分别表示以为底的极大矩形的上边界,左边界,右边界;
首先预处理:找到点(i,j)可以沿伸的的上端点、左端点,右端点 (dp)
For i = 1 to n
For j = 1 to m
u[i][j] = (i-1,j)==1 ? u[i-1][j] : i;
l[i][j] = (i,j-1)==1 ? l[i][j-1] : j;
For j = m to 1
r[i][j] = (i,j+1)==1 ? r[i][j+1] : j;
如图找到了(4,3) 的 上端点、左端点,右端点,但是这些边界并没有组成一个矩形,可以(4,3)的上端点为上边界,找到左右边界,这样就可以找到一个以点(4,3)为底、以点(4,3)上界为高的极大矩形。
For i = 1 to n
For j = 1 to m
if (i-1,j)==1
l[i][j] = max(l[i][j], l[i-1][j]
r[i][j] = min(r[i][j], r[i-1][j]

#include<bits/stdc++.h>
using namespace std; const int N = 1e3+100; int n, m;
int g[N][N];
int u[N][N], l[N][N], r[N][N];
int hh, ll, rr, bb;
char str[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++){
scanf("%s",str+1);
for(int j = 1; j <= m; j++ ){
if(str[j] == '1') g[i][j] = 1;
else g[i][j] = 0;
}
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
u[i][j] = l[i][j] = r[i][j] = 0; for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(g[i][j] == 0) continue;
u[i][j] = g[i-1][j] == 1 ? u[i-1][j] : i;
l[i][j] = g[i][j-1] == 1 ? l[i][j-1] : j;
}
for(int j = m; j >= 1; j--){
if(g[i][j] == 0) continue;
r[i][j] = g[i][j+1] == 1 ? r[i][j+1] : j;
}
}
int ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(g[i][j] == 0) continue;
if(g[i-1][j] == 1) {
l[i][j] = max(l[i][j], l[i-1][j]);
r[i][j] = min(r[i][j], r[i-1][j]);
}
if(ans<(r[i][j]-l[i][j]+1)*(i-u[i][j]+1)){
hh = u[i][j] , bb =i;
rr = r[i][j],ll=l[i][j];
ans = (r[i][j]-l[i][j]+1)*(i-u[i][j]+1);
}
}
}
int ans2 = max((rr-ll)*(bb-hh+1), (rr-ll +1)*(bb-hh));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(g[i][j] == 0) continue;
if(hh==u[i][j]&&bb==i&&ll==l[i][j]&&rr==r[i][j])
continue;
if(ans2<(r[i][j]-l[i][j]+1)*(i-u[i][j]+1)){
ans2=(r[i][j]-l[i][j]+1)*(i-u[i][j]+1);
}
}
}
cout << ans2 << endl;
return 0;
}
悬线法的学习可以参考这篇博客(小声bb:虽然感觉现在没什么用,还不如单调栈)
https://blog.csdn.net/dbc_121/article/details/77503611
2019牛客暑期多校训练营(第二场) H-Second Large Rectangle(单调栈)的更多相关文章
- 牛客多校第二场H Second Large Rectangle 单调栈or悬线法
Second Large Rectangle 题意 给出n*m的01矩阵,问由1组成的第二大的矩阵的大小是多少? 分析 单调栈(or 悬线法)入门题 单调栈 预处理出每一个点的最大高度,然后单调栈每一 ...
- 2019 牛客暑期多校 第二场 H Second Large Rectangle (单调栈)
题目:https://ac.nowcoder.com/acm/contest/882/H 题意:一个大的01矩阵,然后现在要求第二大的全一矩阵是多少 思路:在这里我们首先学习一下另一个东西,怎么求直方 ...
- 2020牛客暑期多校训练营 第二场 K Keyboard Free 积分 期望 数学
LINK:Keyboard Free 我要是会正经的做法 就有鬼了. 我的数学水平没那么高. 三个同心圆 三个动点 求围成三角形面积的期望. 不会告辞. 其实可以\(n^2\)枚举角度然后算出面积 近 ...
- 2020牛客暑期多校训练营 第二场 J Just Shuffle 置换 群论
LINK:Just Shuffle 比较怂群论 因为没怎么学过 置换也是刚理解. 这道题是 已知一个置换\(A\)求一个置换P 两个置换的关键为\(P^k=A\) 且k是一个大质数. 做法是李指导教我 ...
- 2020牛客暑期多校训练营 第二场 I Interval 最大流 最小割 平面图对偶图转最短路
LINK:Interval 赛时连题目都没看. 观察n的范围不大不小 而且建图明显 考虑跑最大流最小割. 图有点稠密dinic不太行. 一个常见的trick就是对偶图转最短路. 建图有点复杂 不过建完 ...
- 2020牛客暑期多校训练营 第二场 C Cover the Tree 构造 贪心
LINK:Cover the Tree 最受挫的是这道题,以为很简单 当时什么都想不清楚. 先胡了一个树的直径乱搞的贪心 一直过不去.后来意识到这类似于最经典长链剖分优化贪心的做法 然后那个是求最大值 ...
- 2020牛客暑期多校训练营 第二场 B Boundary 计算几何 圆 已知三点求圆心
LINK:Boundary 计算几何确实是弱项 因为好多东西都不太会求 没有到很精通的地步. 做法很多,先说官方题解 其实就是枚举一个点 P 然后可以发现 再枚举一个点 然后再判断有多少个点在圆上显然 ...
- 2020牛客暑期多校训练营 第二场 A All with Pairs 字符串hash KMP
LINK:All with Pairs 那天下午打这个东西的时候状态极差 推这个东西都推了1个多小时 (比赛是中午考试的我很困 没睡觉直接开肝果然不爽 一开始看错匹配的位置了 以为是\(1-l\)和\ ...
- 2019牛客暑期多校训练营(第九场) D Knapsack Cryptosystem
题目 题意: 给你n(最大36)个数,让你从这n个数里面找出来一些数,使这些数的和等于s(题目输入),用到的数输出1,没有用到的数输出0 例如:3 4 2 3 4 输出:0 0 1 题解: 认真想一 ...
随机推荐
- NP问题/NP完全问题(NP-complete problem)如何判断是否是NP完全问题
在算法复杂度分析的过程中,人们常常用特定的函数来描述目标算法,随着变量n的增长,时间或者空间消耗的增长曲线,近而进一步分析算法的可行性(有效性). 引入了Big-O,Big-Ω,来描述目标算法的上限. ...
- Label_table
<table border(边框) = "" width = height = align = bordercolor(边框色) = cellspacing 表格边框与单元格 ...
- Mysql-Incorrect string value
[问题描述] com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect string value: '\xF0\x9F\x8E\x8 ...
- 跨域的几种方式以及call(),apply() bind()方法的作用和区别
jsonp: jsonp 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议. 一个是描述信息的格式,一个是信息传递 ...
- tensorflow安装使用过程错误及解决方法
tensorflow2.x 使用过程中常见错误(持续更新) 安装配置,使用tensorflow训练模型,转换为tflite模型,并部署与移动端过程中,虽然不难,但是也常出现一些莫名其妙的问题,下面简单 ...
- 【分布式锁的演化】终章!手撸ZK分布式锁!
前言 这应该是分布式锁演化的最后一个章节了,相信很多小伙伴们看完这个章节之后在应对高并发的情况下,如何保证线程安全心里肯定也会有谱了.在实际的项目中也可以参考一下老猫的github上的例子,当然代码没 ...
- MySQL使用SQL操作数据表的增加、修改和删除
表的修改和删除 修改 -- 修改表名称 -- ALTER TABLE 旧表名 RENAME AS 新表名 ALTER TABLE test RENAME AS test1 -- 增加表字段 -- AL ...
- load data local带来的安全问题
load data默认读的是服务器上的文件,但是加上local参数后,就可以将本地具有访问权限的文件加载到数据库中,这在带来方便的同时,也带来了以下安全问题, 可以任意加载本地文件到数据库, 在web ...
- 高效率同步降压变换器,24V转3.3V降压芯片
PW2312是一个高频,同步,整流,降压,开关模式转换器与内部功率MOSFET.它提供了一个非常紧凑的解决方案,以实现1.5A的峰值输出电流在广泛的输入电源范围内,具有良好的负载和线路调节. PW23 ...
- 转 16 jmeter中的监听器以及测试结果分析
16 jmeter中的监听器以及测试结果分析 常用监听器 断言结果.查看结果树.聚合报告.Summary Report.用表格查看结果.图形结果.aggregate graph等 指标分析 -Sa ...