题目:
见https://www.acwing.com/problem/content/154/
思路:
枚举每一行,把每一行看作最大直方图的矩形这题来做,对数据需要进行预处理,详情见代码
代码:
#include<iostream>
#include<algorithm>
#include<climits>
using namespace std;
const int N=1010;
int rec[N][N];
int stk[N];
int tt;
int left1[N],right1[N];
int n,m;
void find(int *a,int *s)//维护单调栈并且找出第一个比a[i]小的数,把该数的下标入栈
{
for(int j=0;j<=m+1;j++)
{
while(tt>0&&a[stk[tt]]>=a[j]) tt--;//维护单调栈
s[j]=stk[tt];//用s记录第一个比a[i]小的数的位置
stk[++tt]=j;//该点入栈
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
char c;
cin>>c;
if(c=='R')
rec[i][j]=0;
else if(c=='F')
rec[i][j]=rec[i-1][j]+1;
}//转化问题,预处理操作
for(int i=1;i<=n;i++)
{
rec[i][0]=-1;
rec[i][m+1]=-1;
}//这一步也是为了维护单调栈时更加方便
int res=INT_MIN;
for(int i=1;i<=n;i++)
{
tt=0;
find(rec[i],left1);
reverse(rec[i],rec[i]+m+2);//翻转该行的数,个人认为也可以不翻转,不翻转就只需要再写一个函数而已,对下标变化的要求减少,降低了很多难度
find(rec[i],right1);
for(int j=1;j<=m;j++)
res=max(res,3*rec[i][m+1-j]*(m-right1[m+1-j]-left1[j]));//这里的下标长度等变化折磨了我一小时,建议直接举例子
}
cout<<res<<endl;
return 0;
}