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

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

题意

在01矩阵中找到第二大的全1矩阵,若没有第二大的矩阵则输出0。

题目链接:

https://ac.nowcoder.com/acm/contest/882/H

题解

这个题目题意看起来很简单,但是真的把我打自闭了,矩阵n,m大小在1~1000。如果暴力的话O(n3)还是会TLE的。
以下讲讲我的思路。搞清楚第二大矩阵,首先我们要解决的问题是:

  1. 怎么判断矩阵

  2. 怎么找到最大矩阵

  3. 怎么找到第二大矩阵

    一、判断矩阵的方法很简单,我们只要确保矩阵里面全是1就好了。
    二、找到最大矩阵有一点小技巧。
      举例来说:5*5的矩阵
      1 1 1 1 1
      1 1 1 1 0
      1 1 1 0 0
      1 1 0 0 0
      1 1 0 0 0
      我们定义一个数组h来记录这个矩阵的高,从上加到下,如果为0则定义为0,那么h矩阵就是:
      1 1 1 1 1
      2 2 2 2 0
      3 3 3 0 0
      4 4 0 0 0
      5 5 0 0 0
      以h矩阵的h[i][j]为矩阵的左下角,用数字d当作矩阵的宽度,从1开始递增(直到右边的数为比他小为止)矩阵的大小则为d*h。
      三、找到第二大的矩阵其实很简单
      用max1和max2来记录矩阵的最大值和一个比最大值小的数。然后再去维护这两个数,遇到比最大值大的就修改最大值,遇到在两个数之间的就修改第二个值。
    所以我们可以算出所有矩阵的大小,然后通过max1和max2来找到第二大的矩阵
    没错,虽然说我的思路很清晰,但是还是搞不定呀。。。
    询问过学长后才知道需要用【单调栈】来优化算法

单调栈

单调栈顾名思义就是栈里面的元素都是单调性的(单调增或单调减)
这里用单调栈储存数组的下标。j从1遍历到m,如果h[j]<h[栈顶]的话就计算该矩阵的面积,然后将栈顶元素弹出,再重复比较h[j]和h[栈顶]。最后把h[j]压入栈中。
由于使用单调栈,我们求得是最大子矩阵,所以要把包含在最大子矩阵得次大
子矩阵的情况算进去,所以对于取值的时候要特判 (d-1,h) 和 (d,h-1),d代表底,h代表高。
例如:2*3的矩阵
1 1 0 0
1 1 1 1
h矩阵为:
1 1 0 0
2 2 1 1
i = 1时:先将0压入栈中,再将1、2压入栈中,栈的元素为0 1 2 。
因为h[3] == 0 < 1,所以计算面积 max1= 1,max2 = 2。
i = 2时:先将0压入栈中,再将1、2压入栈中,栈的元素为0 1 2 。
因为h[3] == 1 < 2,所以计算面积 max1= 2,max2 = 4。
然后栈的元素再变为0 3 4,当4后面没有数了,直接计算。
最后算出面积是 max1= 4,max2 = 4。

AC代码

#include<string.h>
#include<stdio.h>
#include<stack>
#include<algorithm>
using namespace std;
  
int matrix[1005][1005];
int h[1005];
int r[1005];
int l[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值