[tyvj]P1939玉蟾宫[单调栈]
玉蟾宫
——!x^n+y^n=z^n
背景
有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。
描述
这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda。
现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着'F'并且面积最大。
但是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为S,它们每人给你S两银子。
输入格式
第一行两个整数N,M,表示矩形土地有N行M列。
接下来N行,每行M个用空格隔开的字符'F'或'R',描述了矩形土地。
输出格式
输出一个整数,表示你能得到多少银子,即(3*最大'F'矩形土地面积)的值。
测试样例1
输入
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
输出
45
考虑下面这种情况,就是所有宽为1的矩形的底在同一直线上,我们可以考虑用栈来维护,为什么呢?
注意到对于每一个小矩形,他对答案的贡献为向左延伸和向右延伸的最大值,如果后面加进一个低一点的元素,那这个就没啥用了,何不如直接删掉?
用单调栈,一个记录栈顶元素,另一个记录在当前索引应删除的元素。
那只需预处理出s[i][j]第i行,第j列,能向右延长的最大值,每次枚举底部,那我们只需要每次加入元素并更新答案即可。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 inline int read(); 6 int Max(int x,int y){return x>y?x:y;} 7 namespace lys{ 8 const int N = 1e3 + 7 ; 9 int s[N][N],s1[N],s2[N],a[N][N]; 10 int n,m,ans,top,del; 11 void work(int row){ 12 top=0; 13 for(int i=1;i<=n+1;i++){ 14 del=i; 15 while(top&&s1[top]>=s[i][row]){ 16 ans=Max(ans,s1[top]*(i-s2[top])); 17 del=s2[top--]; 18 } 19 s1[++top]=s[i][row];s2[top]=del; 20 } 21 } 22 int main(){ 23 int i,j; 24 char c; 25 n=read(); m=read(); 26 for(i=1;i<=n;i++) 27 for(j=1;j<=m;j++){ 28 c=getchar(); 29 while(c!='F'&&c!='R') c=getchar(); 30 if(c=='F') a[i][j]=1; 31 } 32 for(i=1;i<=n;i++) 33 for(j=m;j>=1;j--) 34 s[i][j]=a[i][j]?s[i][j+1]+1:0; 35 for(i=1;i<=m;i++) work(i); 36 printf("%d\n",3*ans); 37 return 0; 38 } 39 } 40 int main(){ 41 lys::main(); 42 return 0; 43 } 44 inline int read(){ 45 int kk=0,ff=1; 46 char c=getchar(); 47 while(c<'0'||c>'9'){ 48 if(c=='-') ff=-1; 49 c=getchar(); 50 } 51 while(c>='0'&&c<='9') kk=kk*10+c-'0',c=getchar(); 52 return kk*ff; 53 }