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和上一行进行比较,这样其实是求出了一个位置尽量向上扩展的最大面积。

#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
", ans * 3);    
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/7379747.html