玉蟾宫
题目链接:https://www.luogu.org/problemnew/show/P4147
题目背景
有一天,小猫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'矩形土地面积)的值。
输入输出样例
说明
对于50%的数据,1<=N,M<=200
对于100%的数据,1<=N,M<=1000
Sol one :悬线法。(详情参见王知昆dalao大佬的博客)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define LL long long 7 #define RI register int 8 using namespace std; 9 const int INF = 0x7ffffff ; 10 const int N = 1000 + 10 ; 11 12 inline int read() { 13 int k = 0 , f = 1 ; char c = getchar() ; 14 for( ; !isdigit(c) ; c = getchar()) 15 if(c == '-') f = -1 ; 16 for( ; isdigit(c) ; c = getchar()) 17 k = k*10 + c-'0' ; 18 return k*f ; 19 } 20 int n, m ; bool hh[N][N] ; int l[N][N], r[N][N], L[N][N], R[N][N], h[N][N] ; 21 22 int main() { 23 n = read(), m = read() ; 24 for(int i=1;i<=n;i++) 25 for(int j=1;j<=m;j++) { 26 char cc ; cin>>cc ; 27 if(cc == 'F') hh[i][j] = 1 ; 28 } 29 for(int i=1;i<=n;i++) { 30 int t = 0 ; 31 for(int j=1;j<=m;j++) { 32 if(hh[i][j]) l[i][j] = t ; 33 else L[i][j] = 0, t = j ; 34 } 35 t = m+1 ; 36 for(int j=m;j;j--) { 37 if(hh[i][j]) r[i][j] = t ; 38 else R[i][j] = m+1, t = j ; 39 } 40 } 41 int ans = 0 ; 42 for(int i=1;i<=m;i++) R[0][i] = m+1 ; // 第0行一定要做好标记 43 for(int i=1;i<=n;i++) 44 for(int j=1;j<=m;j++) { 45 if(hh[i][j]) { 46 h[i][j] = h[i-1][j]+1 ; 47 L[i][j] = max(L[i-1][j],l[i][j]+1) ; 48 R[i][j] = min(R[i-1][j],r[i][j]-1) ; 49 ans = max(ans,h[i][j]*(R[i][j]-L[i][j]+1)) ; 50 } 51 } 52 printf("%d",ans*3) ; 53 return 0 ; 54 }
Sol two : 单调栈。枚举矩形下届,然后按照这道题:Largest Rectangle in a Histogram做就可以了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<stack> 7 #define LL long long 8 #define RI register int 9 using namespace std; 10 const int INF = 0x7ffffff ; 11 const int N = 1000 + 10 ; 12 13 inline int read() { 14 int k = 0 , f = 1 ; char c = getchar() ; 15 for( ; !isdigit(c) ; c = getchar()) 16 if(c == '-') f = -1 ; 17 for( ; isdigit(c) ; c = getchar()) 18 k = k*10 + c-'0' ; 19 return k*f ; 20 } 21 int n, m, ans = 0 ; int pos[N][N], l[N] ; 22 bool hh[N][N] ; 23 24 inline void solve(int now) { 25 stack<int>s ; 26 for(int i=1;i<=m;i++) { 27 while(s.size() && pos[now][s.top()] >= pos[now][i]) ans = max(ans,(i-l[s.top()]-1)*pos[now][s.top()]), s.pop() ; 28 if(s.size()) l[i] = s.top() ; else l[i] = 0 ; // 不初始化的话这里就要加else 29 s.push(i) ; 30 } 31 while(s.size()) ans = max(ans,(m-l[s.top()])*pos[now][s.top()]), s.pop() ; 32 } 33 34 int main() { 35 n = read(), m = read() ; 36 for(int i=1;i<=n;i++) 37 for(int j=1;j<=m;j++) { 38 char cc ; cin>>cc ; 39 if(cc == 'F') hh[i][j] = 1 ; 40 } 41 for(int i=1;i<=n;i++) 42 for(int j=1;j<=m;j++) 43 if(!hh[i][j]) pos[i][j] = 0 ; else pos[i][j] = pos[i-1][j]+1 ; 44 for(int i=1;i<=n;i++) solve(i) ; 45 printf("%d",ans*3) ; 46 return 0 ; 47 }