【2019牛客暑期多校训练营(第二场) - H】Second Large Rectangle(单调栈,全1子矩阵变形)

题干:

链接:https://ac.nowcoder.com/acm/contest/882/H
来源:牛客网
 

题目描述

Given a N×MN \times MN×M binary matrix. Please output the size of second large rectangle containing all "1"\texttt{"1"}"1".

Containing all "1"\texttt{"1"}"1" means that the entries of the rectangle are all "1"\texttt{"1"}"1".
 

A rectangle can be defined as four integers x1,y1,x2,y2x_1, y_1, x_2, y_2x1​,y1​,x2​,y2​ where 1≤x1≤x2≤N1 \leq x_1 \leq x_2 \leq N1≤x1​≤x2​≤N and 1≤y1≤y2≤M1 \leq y_1 \leq y_2 \leq M1≤y1​≤y2​≤M. Then, the rectangle is composed of all the cell (x, y) where x1≤x≤x2x_1 \leq x \leq x_2x1​≤x≤x2​ and y1≤y≤y2y_1 \leq y \leq y2y1​≤y≤y2. If all of the cell in the rectangle is "1"\texttt{"1"}"1", this is a valid rectangle.

 

Please find out the size of the second largest rectangle, two rectangles are different if exists a cell belonged to one of them but not belonged to the other.

输入描述:

 

The first line of input contains two space-separated integers N and M.
Following N lines each contains M characters cijc_{ij}cij​.

1≤N,M≤10001 \leq N, M \leq 10001≤N,M≤1000
N×M≥2N \times M \geq 2N×M≥2
cij∈"01"c_{ij} \in \texttt{"01"}cij​∈"01"

输出描述:

 

Output one line containing an integer representing the answer. If there are less than 2 rectangles containning all "1"\texttt{"1"}"1", output "0"\texttt{"0"}"0".

示例1

输入

复制

1 2
01

输出

复制

0

示例2

输入

复制

1 3
101

输出

复制

1

题目大意:

给定一个N*M的01矩阵,求 不严格第二大 的全1子矩阵。(严格第二大就是,你求出的值必须和第一大的 值不同)

解题报告:

  求第一大的是单调栈裸题。这题是第二大通过观察不难发现,最终答案一定是某个候选的最大子矩阵的子矩阵。而在这些子矩阵中,肯定是去掉某一行或者去掉某一列是最优的。所以做法就是先O(N*M)求出所有最大子矩阵,然后枚举这些矩阵,维护最大值和次大值就好了。但是要注意去重,因为假设是一行三列"111"这种情况的话,那答案肯定是不对的,因为你以每一个1为底都是对应同一个矩形,也就是这样会算重复。

这里我采用的处理办法是在记录最大值次大值的同时记录对应的左端点,右端点和高。(虽然按理来说不能记录高,而应该记录下底和上底,但是这个题我是按照下底进行遍历的,而遍历每一行的时候都清空了我上一行维护的“左端点,右端点和高”,所以这样就足够去重的要求了,所以不需要记录下底和上底)。虽然去重是没有问题的,但是其实在考虑矩阵的时候我这样做不是严格正确的,因为你去掉某一列的时候,默认是去掉了最右列,按理来说也可以去掉最左列呀,,也就是说本身会生成两个次小子矩阵的你只考虑了一个,所以程序其实是有点问题,但是因为这个题求的是第2大,所以肯定还是能AC的。因为你求的这些肯定比最大子矩阵要小,所以肯定符合要求,但是如果题目让你求第三大的,这样就不太行了。。。你得把:去掉左列,去掉右列,去掉上行,去掉下行,都加入考虑中,才是正确答案。。(或许这题还可以再出一遍??emmm)

以上是我采用的处理办法,但是不具有通用性,他如果让你求第8大,那你维护八个变量不成?所以这里正解给出的是加入vector中,然后对vector排序,然后去重(这一点一定别忘了,但是你要是这么写的话就得记录对应的左端点,右端点和下底上底了,不能只记录高了),然后输出第8大。(因为这题是第二大所以直接上pq维护两个元素也行)

AC代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<stack>using namespace std;
const int MAX = 1000 + 5;
int n,m;
int maze[MAX][MAX];
int L[MAX],R[MAX];void getl(int i) {stack<int > sk;//要找他左侧的第一个严格比他小的元素 所以需要从左向右维护一个严格单调递增栈for(int j = 1; j<=n; j++) {while(!sk.empty() && maze[i][sk.top() ]>=maze[i][j] ) sk.pop();if(sk.empty() ) L[j] = 0;else L[j] = sk.top();sk.push(j);}}
void getr(int i) {stack<int > sk;//要找他右侧的第一个严格比他小的元素 所以需要从右向左维护一个严格单调递增栈for(int j = n; j>=1; j--) {while(!sk.empty() && maze[i][sk.top() ]>=maze[i][j] ) sk.pop();if(sk.empty() ) R[j] = n+1;else R[j] = sk.top();sk.push(j);}}
void init() {for(int i = 1; i<=m; i++)for(int j = 1; j<=n; j++)maze[i][j]=0;
}
int main()
{while(~scanf("%d %d",&m,&n) ) {//m行n列init();for(int i = 1; i<=m; i++) {for(int j = 1; j<=n; j++) {int tmp;scanf("%1d",&tmp);if(tmp==1) {maze[i][j]=maze[i-1][j]+1;}}}//至此我们已经有了截止第i行的(1~i)每一个j的连续高度,int maxx=0,ci = 0,tmp,tmp1,tmp2,mx1=-1,mx2=-1,mh=-1;for(int i = 1; i<=m; i++) {getl(i);getr(i);mx1=-1,mx2=-1,mh=-1;for(int j = 1; j<=n; j++) {tmp = maze[i][j] * (R[j] - L[j] -1);tmp1 = maze[i][j] * (R[j] - L[j] -2);tmp2 = (maze[i][j]-1) * (R[j] - L[j] -1);int curl=L[j]+1,curr = R[j]-1,curh = maze[i][j];if(tmp > maxx) {ci = maxx;mx1=curl,mx2=curr,mh=curh;maxx = tmp;}else if(tmp > ci && (mx1!=curl || mx2!=curr || mh!=curh)) {ci = tmp;}if(tmp1 >= tmp2) {tmp = tmp1;curr--;}else {tmp = tmp2;curh--;}
//              tmp = max(tmp1,tmp2);if(tmp > maxx) {ci = maxx;mx1=curl,mx2=curr,mh=curh;maxx = tmp;}else if(tmp > ci && (mx1!=curl || mx2!=curr || mh!=curh)) {ci = tmp;}}
//          printf("\n");}printf("%d\n",ci);}return 0 ;}
/*
1 3
111
*/

然后你会发现简短好多:(忽然发现好像不用考虑减一行呀、、因为那肯定在上一行当下底的时候算过了、、)

(其实还是因为单调栈的打开方式不太一样,我是遍历到第i个元素的时候处理第i个元素,然后push(i)进去,他是pop(j)的时候才开始处理每一个j,我要是这么写的话应该也短不少,而且有的时候只能用第二种方式,比如后面那次牛客多校、、)

这样写的意思就是把所有宽度的缩减都考虑进去了。但是这样写的话应该可以卡T掉,,因为你构造一个左下全1的下三角矩阵,就能卡成O(N*M*M)、、因为他那个cnt的动作太耗时了。(本来写的是最下面那个代码)

#include<bits/stdc++.h>
using namespace std;
const int M = 1e3+5;
int dp[M][M];
int ddz[M],w[M];
vector<int> ans;
int n,m;void solve(int *f){int top = 0;ddz[top] = -1;f[m+1] = -1;for(int i=1;i<=m+1;i++){if(ddz[top] <= f[i]) ddz[++top] = f[i];else {int cnt = 0;//接下来把所有宽度的都加进去while(top && ddz[top] > f[i]) {cnt++;ans.push_back(ddz[top] * cnt);top--;}while(cnt--) ddz[++top] = f[i];ddz[++top] = f[i];}}
}int main(){char c[M];while(~scanf("%d%d",&n,&m)) {ans.clear();for(int i=1;i<=n;i++){scanf("%s",c);for(int j=1;j<=m;j++) dp[i][j] = c[j-1] == '0'? 0 : dp[i-1][j]+1;}for(int i=1;i<=n;i++) solve(dp[i]);sort(ans.begin(),ans.end());/*考虑特例*/int sz = ans.size();if(sz<=1) printf("0\n");printf("%d\n", ans[sz-2]);}return 0;
}

他本来的solve函数是这么写的:

void solve(int *f){int top = 0;ddz[top] = -1;f[m+1] = -1;for(int i=1;i<=m+1;i++){/*等于时是否弹出这需要自己注意一下,就是严不严格单调的选择*/if(ddz[top]<f[i]) ddz[++top]=f[i],w[top]=1;else{int width = 0;/*此处注意要先加宽度*/while(top&&f[i]<ddz[top]){ width+=w[top],ans.push_back(ddz[top]*width),ans.push_back(ddz[top]*(width-1));top--;}/*我的做法是 : 等于是加入,不严格单调*/ddz[++top]=f[i],w[top]=width+1;}}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439912.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Apollo进阶课程⑭ | Apollo自动定位技术——三维几何变换和坐标系介绍

目录 1.三维几何变换---旋转 2.三维几何变换----平移 2.1刚体的位置和朝向 3. 坐标系 3.1 ECI地心惯性坐标系 3.2 ECFF地心地固坐标系 3.3当地水平坐标系 3.4 UTM坐标系 3.5 车体坐标系 3.6IMU坐标系 3.7 相机坐标系 3.8 激光雷达坐标系 3.9 无人车定位信息中涉及…

一步步编写操作系统 09 写个mbr

有点不好意思了&#xff0c;说了好久&#xff0c;才说到实质性的东西&#xff0c;好了&#xff0c;赶紧给客官上菜。 代码2-1&#xff08;c2/a/boot/mbr.S&#xff09;1 ;主引导程序2 ;------------------------------------------------------------3 SECTION MBR vstart0x7c…

【2019牛客暑期多校训练营(第二场)- F】Partition problem(dfs,均摊时间优化)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/882/F 来源&#xff1a;牛客网 Given 2N people, you need to assign each of them into either red team or white team such that each team consists of exactly N people and the total competi…

Apollo进阶课程 ⑮丨Apollo自动定位技术详解—百度无人车定位技术

目录 1.百度无人车定位进化历程 2.百度自动驾驶应用的定位技术 2.1GNSS定位技术 2.2载波定位技术 2.3激光点云定位技术 2.4视觉定位技术 原文链接&#xff1a;进阶课程 ⑮丨Apollo自动定位技术详解—百度无人车定位技术 定位的目的是让自动驾驶汽车找到自身确切位置的方法…

一步步编写操作系统 10 cpu的实模式

cpu的实模式 由于mbr在实模式下工作……什么&#xff1f;什么是实模式&#xff1f;这时候有同学打断了我。我心想&#xff0c;这下好办了……哈哈&#xff0c;没有啦&#xff0c;开个玩笑而已。我们这里所说的实模式其实就是8086 cpu的工作环境、工作方式、工作状态&#xff0…

Ubuntu系统中使用搜狗输入法

今天介绍如何在Ubuntu中使用搜狗输入法。&#xff08;Ubuntu版本为16.04&#xff09; 1&#xff09;登陆搜狗官网选择对应系统的搜狗输入法&#xff1a;http://pinyin.sogou.com/linux。 2&#xff09;打开下载目录&#xff0c;命令行输入以下命令&#xff1a; sudo dpkg -i …

【2019牛客暑期多校训练营(第三场)- B】Crazy Binary String(思维,01串,前缀和)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/883/B 来源&#xff1a;牛客网 ZYB loves binary strings (strings that only contains 0 and 1). And he loves equal binary strings\textit{equal binary strings}equal binary strings more, wh…

2.1)深度学习笔记:深度学习的实践层面

目录 1&#xff09;Train/Dev/Test sets 2&#xff09;Bias/Variance 3&#xff09;Regularization&#xff08;重点&#xff09; 4&#xff09;Why regularization reduces overfitting&#xff08;理解&#xff09; 5&#xff09;Dropout Regularization&#xff08;重点…

一步步编写操作系统 12 代码段、数据段、栈和cpu寄存器的关系

先说下什么是寄存器。 寄存器是一种物理存储元件&#xff0c;只不过它是比一般的存储介质要快&#xff0c;能够跟上cpu的步伐&#xff0c;所以在cpu内部有好多这样的寄存器用来给cpu存取数据。 先简短说这一两句&#xff0c;暂时离开一下主题&#xff0c;咱们先看看相对熟悉一…

【2019牛客暑期多校训练营(第三场)- F】Planting Trees(单调队列,尺取)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/883/F 来源&#xff1a;牛客网 The semester is finally over and the summer holiday is coming. However, as part of your universitys graduation requirement, you have to take part in some …

Apollo进阶课程⑯丨Apollo感知之旅——感知概貌

原文链接&#xff1a;进阶课程⑯丨Apollo感知之旅——感知概貌 上周阿波君为大家详细介绍了「进阶课程⑮| Apollo无人车自定位技术入门」。 我们人类天生就配备多种传感器&#xff0c;眼睛可以看到周围的环境&#xff0c;耳朵可以用来听&#xff0c;鼻子可以用来嗅&#xff0c;…

一步步编写操作系统 13 栈

栈到底是什么玩意 cpu中有栈段SS寄存器和栈指针SP寄存器&#xff0c;它们是用来指定当前使用的栈的物理地址。换句话说&#xff0c;要想让cpu运行&#xff0c;必须得有栈。栈是什么?干吗用的&#xff1f;本节将给大家一个交待。 还记得数据结构中的栈吗&#xff1f;那是逻辑…

【2019牛客暑期多校训练营(第二场)- E】MAZE(线段树优化dp,dp转矩阵乘法,线段树维护矩阵乘法)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/882/E?&headNavacm 来源&#xff1a;牛客网 Given a maze with N rows and M columns, where bijb_{ij}bij​ represents the cell on the i-row, j-th column. If bi,j"1"b_{i, j} …

Apollo进阶课程⑰丨Apollo感知之旅——传感器选择和安装

目录 1.激光雷达 2.相机 3.Radar毫米波 4.安装传感器 原文链接&#xff1a;进阶课程⑰丨Apollo感知之旅——传感器选择和安装 上周阿波君为大家详细介绍了「进阶课程⑯ Apollo感知之旅——感知概况」。 传感器是一种检测装置&#xff0c;能感受到被测量的信息&#xff0c;…

一步步编写操作系统 14 CPU与外设通信——IO接口 上

介绍显卡之前&#xff0c;必须得和大家交待清楚&#xff0c;那么多的外部设备&#xff0c;cpu是如何与他们交流。 大家都学过微机接口技术吧&#xff1f;没学过也没关系&#xff0c;反正我也只是笼统地说说^_^&#xff0c;保证大家一定能看得懂。 按理说&#xff0c;如果硬件…

2.2)深度学习笔记:优化算法

目录 1&#xff09;Mini-batch gradient descent&#xff08;重点&#xff09; 2&#xff09;Understanding mini-batch gradient descent 3&#xff09;Exponentially weighted averages 4&#xff09;Understanding exponetially weighted averages 5&#xff09;Bias c…

【POJ - 2019】Cornfields(二维st表,模板)

题干&#xff1a; FJ has decided to grow his own corn hybrid in order to help the cows make the best possible milk. To that end, hes looking to build the cornfield on the flattest piece of land he can find. FJ has, at great expense, surveyed his square fa…

虚拟机安装Linux(vmware + ubuntu)

VMWare 提取码&#xff1a;7zph 建议官网下载比较新&#xff0c;还快一点 https://www.vmware.com/products/workstation-pro.htmlubantu 下载地址 安装过程都差不多可以参考 VMware下安装Ubuntu系统图文详细教程_master-CSDN博客_vmware安装ubuntu系统 出现蓝屏问题可以参考…

Apollo进阶课程⑱丨Apollo感知之旅——传感器标定

目录 传感器标定 标定的目的 传感器标定算法 标定案例解析 3D标定间制作 Cmaera-to-Camera外参标定 Lidar-to-Camera外参标定 Lidar-to-Lidar外参标定 Lidar内参标定 Lidar-to-GPS外参标定 自然场景的Lidar-to-Camera外参标定 自然场景的Bifocal Camera外参标定 C…

一步步编写操作系统 15 CPU与外设通信——IO接口,下

既然都说到IO接口了&#xff0c;不知道各位有没有疑问&#xff0c;cpu是怎样访问到IO接口呢&#xff1f;肯定得有个链路吧&#xff1f;什么&#xff1f;有隐约听到有同学开玩笑说&#xff1a;cpu用无线访问其它设备。哈哈&#xff0c;不知道各位听说过没有&#xff0c;无线的终…