题解
- 我们可以枚举每一行,记录这一行每列连续 F 的个数(如图枚举到第四行) ,F的个数可以从第一行递推求出,这样问题就转化成算法竞赛进阶指南—0x11(栈) 直方图中最大的矩形
- 对于每一行,我们可以枚举每个高度所能组成的面积最大的长方形,然后取一个最大值即可。就看题中的样例,对于第四列的,只有左右两边的高度>=4 才能组成要枚举的长方形,那么就要求左右两边的小长方形高度最小为4,可以看到,左边没有,右边2个,所以面积为( 7 - 3 - 1 ) * 4 = 12
- 那么转化就是,我们可以记录左边离他最近且小于它的高度的下标,右边离他最近且小于它高度的下标,那么(右-左-1)就是这个高度对应的最长的长度,这不就是单调栈的应用嘛
代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
int n, m;
char g[N][N];
int f[N][N];
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> g[i][j];
if (g[i][j] == 'F') f[i][j] = f[i - 1][j] + 1;
else f[i][j] = 0;
}
}
int res = 0;
for (int i = 1; i <= n; i++) {
int stk[N], tt = 0, l[N], r[N];
for (int j = 1; j <= m; j++) {
while (tt && f[i][stk[tt]] >= f[i][j]) tt--;
if (tt) l[j] = stk[tt];
else l[j] = 0;
stk[++tt] = j;
}
tt = 0;
for (int j = m; j > 0; j--) {
while (tt && f[i][stk[tt]] >= f[i][j]) tt--;
if (tt) r[j] = stk[tt];
else r[j] = m + 1;
stk[++tt] = j;
}
for (int j = 1; j <= m; j++) {
res = max(res, (r[j] - l[j] - 1) * f[i][j]);
}
}
cout << res * 3 << endl;
return 0;
}