1. 程式人生 > >【bzoj3039】玉蟾宮 懸線法(單調棧)

【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<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
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; }