【bzoj3039】玉蟾宫 悬线法(单调栈)

Description

有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。
这片土地被分成N*M个格子,每个格子里写着’R’或者’F’,R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda。
现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着’F’并且面积最大。
但是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为S,它们每人给你S两银子。

Input

第一行两个整数N,M,表示矩形土地有N行M列。
接下来N行,每行M个用空格隔开的字符’F’或’R’,描述了矩形土地。

Output

输出一个整数,表示你能得到多少银子,即(3*最大’F’矩形土地面积)的值。

Sample Input

5 6

R F F F F F

F F F F F F

R R R F F F

F F F F F F

F F F F F F

Sample Output

45

HINT

对于50%的数据,1<=N,M<=200

对于100%的数据,1<=N,M<=1000

Source

Poetize4


可以记录每个点往下至多多少个F

然后对于每一行都做一个类似于【最大矩形面积并】什么的…

维护一个单调递增的单调栈,弹栈过程中累计弹出元素的宽度和,每弹出一个就用弹出高度×累计宽度更新答案。
最后给当前矩形的宽度加上累计宽度,入栈。
扫描结束后,依次弹出栈顶元素,按照相同方法更新答案,直至栈为空。

n^2过,以前在codevs都是n^3水过的…数据弱……

#include
#include
#include
#include
#include
using namespace std;

const int SZ = 1010;

int dsum[SZ][SZ],n,m;
char maps[SZ][SZ];

struct haha{
    int w,h;
}S[SZ];

int top = 0;

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i ++)
        for(int j = 1;j <= m;j ++)
        {
            char opt[3];
            scanf("%s",opt);
            maps[i][j] = opt[0];
        }
    for(int i = n;i >= 1;i --)
        for(int j = 1;j <= m;j ++)
            if(maps[i][j] == 'F')
                dsum[i][j] = dsum[i + 1][j] + 1;

    int ans = 0;
    for(int i = 1;i <= n;i ++)
    {
        for(int j = 1;j <= m;j ++)
        {
            int d = 0;
            while(top && S[top].h > dsum[i][j])
                d += S[top].w,ans = max(ans,d * S[top].h),top --;
            S[++ top] = (haha){d + 1,dsum[i][j]};
        }
        int d = 0;
        while(top)
            d += S[top].w,ans = max(ans,d * S[top].h),top --;
    }
    printf("%d\n",ans * 3);
    return 0;
}

你可能感兴趣的:(===数据结构===,栈/队列)