【bzoj3039】玉蟾宮 懸線法(單調棧)
阿新 • • 發佈:2019-02-10
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;
}