很明显是单调栈。
对于一个点,我们找出它往上最多到哪里,(往上最多时)往左往右最多到哪里。
往上的话就直接用dp求出来。
然后考虑往左(往右同理)
设a[j]为上边F的个数,l[j]为左边F的个数。
那么l[j]要怎么求呢?
我们需要找到最后一个a[k]< a[j] (k < j)
找到k就可以用单调栈维护,
单调栈维护a数组,从栈顶到栈底递减
然后就可以发现,如果栈中存在a[j]还要大的数,那么就可以直接把这个数删除,因为a[j]既比这个数小,右在这个数的后面,所以以后都不会用到这个数。
把比a[j]大的数都删除以后,这个时候栈顶tp就是我们要求的,因为栈维护的a是从左往右递增的呀!
不过注意处理好栈的边界问题。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1e3 + 10, inf = 0x3f3f3f3f;
int n, m, up[N][N], l[N][N], r[N][N]; bool a[N][N];
int tp, sta[N], f[N];
int main() {
cin >> n >> m; char s[3];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
scanf("%s", s);
if (s[0] == 'F') a[i][j] = 1;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (!a[i][j]) up[i][j] = 0;
else up[i][j] = up[i - 1][j] + 1;
for (int i = 1; i <= n; i++) {
tp = 0; f[0] = 0;
for (int j = 1; j <= m; j++) {
while (tp && sta[tp] >= up[i][j]) tp--;
l[i][j] = j - f[tp];
sta[++tp] = up[i][j]; f[tp] = j;
}
tp = 0; f[0] = m + 1;
for (int j = m; j >= 1; j--) {
while (tp && sta[tp] >= up[i][j]) tp--;
r[i][j] = f[tp] - j;
sta[++tp] = up[i][j]; f[tp] = j;
}
}
int maxx = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
maxx = max(maxx, (l[i][j] + r[i][j] - 1) * up[i][j]);
cout << maxx * 3 << endl; return 0;
}