类型:单调栈
传送门:>Here<
题意:求一个$01$矩阵中最大子矩形(全是$1$)的面积
解题思路
单调栈的一个经典应用
考虑维护一个数组$p[i][j]$表示$(i,j)$往上最多有多少个连续的$1$。于是问题就转化为上一题的问题了,$p$即为高度,往左右扩散,利用单调栈求即可。总复杂度$O(n^2)$
个人认为,会做这类题的关键还是彻底弄懂上一题
Code
/*By DennyQi 2018.8.18*/ #include <cstdio> #include <queue> #include <cstring> #include <algorithm> #define r read() #define Max(a,b) (((a)>(b)) ? (a) : (b)) #define Min(a,b) (((a)<(b)) ? (a) : (b)) using namespace std; typedef long long ll; const int MAXN = 10010; const int MAXM = 27010; const int INF = 1061109567; inline int read(){ int x = 0; int w = 1; register int c = getchar(); while(c ^ '-' && (c < '0' || c > '9')) c = getchar(); if(c == '-') w = -1, c = getchar(); while(c >= '0' && c <= '9') x = (x<<3) + (x<<1) + c - '0', c = getchar();return x * w; } int N,M,top,ans,cnt; char c[2]; int a[1010][1010],p[1010][1010],h[1010],w[1010]; int main(){ scanf("%d %d",&N,&M); getchar(); for(int i = 1; i <= N; ++i){ for(int j = 1; j <= M; ++j){ scanf("%s",c); a[i][j] = (c[0] == 'F' ? 1 : 0); } } for(int i = 1; i <= N; ++i){ for(int j = 1; j <= M; ++j){ if(a[i][j]){ p[i][j] = p[i-1][j] + 1; } else{ p[i][j] = 0; } } } for(int i = 1; i <= N; ++i){ top = 0; for(int j = 1; j <= M; ++j){ if(!top || p[i][j] > h[top]){ h[++top] = p[i][j]; w[top] = 1; } else{ cnt = 0; while(top > 0 && p[i][j] <= h[top]){ cnt += w[top]; ans = Max(ans, h[top] * cnt); --top; } h[++top] = p[i][j]; w[top] = cnt+1; } } cnt = 0; while(top > 0){ cnt += w[top]; ans = Max(ans, h[top] * cnt); --top; } } printf("%d", ans * 3); return 0; }