牛客竞赛暑期多校训练第二场H-Second Large Rectangle(单调栈)

Given a N×M binary matrix. Please output the size of second large rectangle containing all “1”.

  • 题目描述:给定一个大小为n×m的矩阵,矩阵中的元素为1或者0,求这个矩阵中的第二大全1矩阵,如果这个矩阵中全1矩阵的个数不够两个就输出0.其中第二大矩阵可以由最大的生成。(这个在题目里我一直没读到,就一直wa)
  • 思路:单调栈。我们可以把全1矩阵看作是一个矩形,那么原问题就可以看作是在一个范围内寻找一个第二大的矩形。这样我们就可以在输入的过程中处理一下每一层上每一个点的高度(上面有多少个1),然后单调栈求左右两侧最远可以到哪里构成一个矩形。由于我们需要每一个点都遍历一下,所以有可能出现这种情况:一个矩形,在这一行上,全是1,在遍历这一行的时候,一直在更新最大值,但其实这是一个矩形,所以我们需要记录一下这个矩形处在哪一行,左边到哪里,右边到哪里,这样如果同一个矩形就不会被重复用来刷新最大值。然后每次刷新最大值的时候,顺便算一下在这个最大矩阵的前提下,能够产生的第二大矩形,因为要是第二大,所以要在原矩阵基础上减去最少的一部分,挑高或者宽里面小的那一个减去就可以了。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e3+5;
int height[maxn][maxn], _left[maxn][maxn], _right[maxn][maxn], _stack[maxn];
char maze[maxn][maxn];

int main()
{
    int n, m;
    cin >> n >> m;  getchar();
    for(int i = 1; i <= n; i++)
    {
        int top = 0;
        for(int j = 1; j <= m; j++)
        {
            scanf("%c", &maze[i][j]);
            if(maze[i][j] == '1')
            {
                height[i][j] = 1;
                if(i-1 >= 1)    height[i][j] += height[i-1][j];
            }
            while(top >= 1 && height[i][_stack[top]] >= height[i][j])    top--;
            _left[i][j] = (0 == top) ? 0 : _stack[top];
            _stack[++top] = j;
        }
        top = 0;
        for(int j = m; j >= 1; j--)
        {
            while(top >= 1 && height[i][_stack[top]] >= height[i][j])    top--;
            _right[i][j] = (0 == top) ? m+1 : _stack[top];
            _stack[++top] = j;
        }
        getchar();
    }
    int pos, l, r;
    int fir_max = 0, sec_max = 0;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            int area = height[i][j]*(_right[i][j]-_left[i][j]-1);
            if(0 == fir_max)
            {
                fir_max = area;
                pos = i;    l = _left[i][j], r = _right[i][j];
            }
            else
            {
                if(_left[i][j] == l && _right[i][j] == r && pos == i)   continue ;
                if(area > fir_max)
                {
                    pos = i;    l = _left[i][j], r = _right[i][j];
                    sec_max = fir_max;
                    fir_max = area;
                }
                else if(area > sec_max)
                    sec_max = area;
            }
            area = area-min(_right[i][j]-_left[i][j]-1, height[i][j]);
            if(area > fir_max)
            {
                pos = i;    l = _left[i][j], r = _right[i][j];
                sec_max = fir_max;
                fir_max = area;
            }
            else if(area > sec_max)
                sec_max = area;
        }
    }
    cout << sec_max << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40788897/article/details/96699539