[tyvj]P1939玉蟾宫[单调栈]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[tyvj]P1939玉蟾宫[单调栈]相关的知识,希望对你有一定的参考价值。

[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 }

 

以上是关于[tyvj]P1939玉蟾宫[单调栈]的主要内容,如果未能解决你的问题,请参考以下文章

刷题总结——玉蟾宫(bzoj3039单调栈)

TYVJ1939 玉蟾宫

BZOJ 3039 玉蟾宫

P4147 玉蟾宫

Luogu4147 玉蟾宫

[luoguP1169] [ZJOI2007]棋盘制作(单调栈)