bzoj3039
单调栈
其实是单调栈的变种
维护up,left,right,表示一个点能向左向右向上最大扩展距离,ans就是最大的left*rigth*up
up[i][j]=Map[i-1][j]==1?1:Map[i-1][j]+1
left和right
用单调栈求,每次碰见障碍就把栈中元素弹出,栈中元素左端点在入栈时更新为栈中最左边的位置,右端在弹栈时更新为最右端的位置,然后left和right和上一行进行比较,这样其实是求出了一个位置尽量向上扩展的最大面积。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int N = 1010, inf = 1000000010; int n, m, ans, top; int Map[N][N], Left[N][N], Right[N][N], up[N][N], st[N]; int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) { char s[10]; scanf("%s", s); Map[i][j] = s[0] == 'F' ? 0 : 1; up[i][j] = Map[i - 1][j] == 0 ? up[i - 1][j] + 1 : 1; } for(int i = 1; i <= n; ++i) { int top = 0; for(int j = 1; j <= m; ++j) { if(Map[i][j] == 1) { while(top) { Right[i][st[top - 1]] = Right[i][st[top]]; --top; } } else { Left[i][j] = Right[i][j] = j; if(top) Left[i][j] = Left[i][j - 1]; st[++top] = j; } } while(top) { Right[i][st[top - 1]] = Right[i][st[top]]; --top; } for(int j = 1; j <= m; ++j) if(i > 1 && Map[i - 1][j] != 1) { Left[i][j] = max(Left[i][j], Left[i - 1][j]); Right[i][j] = min(Right[i][j], Right[i - 1][j]); } } for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) if(Map[i][j] == 0) ans = max(ans, up[i][j] * (Right[i][j] - Left[i][j] + 1)); printf("%d\n", ans * 3); return 0; }