https://www.luogu.com.cn/problem/P4147
经典的有障碍的最大子矩阵
悬线法:
先预处理l[i][j],r[i][j],up[i][j]
l[i][j]:表示点(i,j)向左最大扩展的纵坐标
r[i][j]:表示点(i, j)向右最大扩展的纵坐标
up[i][j]:表示点(i,j)向上最大扩展的长度
最后再统计答案的最优解
只有map[i][j]=='F'才更新ans
只有map[i-1][j]也为'F'才更新l,r,up
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=1005;
int l[maxn][maxn],r[maxn][maxn],up[maxn][maxn];
char mp[maxn][maxn];
int n,m,ans;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>mp[i][j],l[i][j]=r[i][j]=j,up[i][j]=1;
for(int i=1;i<=n;i++){
for(int j=2;j<=m;j++)
if(mp[i][j]=='F'&&mp[i][j-1]=='F')
l[i][j]=l[i][j-1];
for(int j=m-1;j>=1;j--)
if(mp[i][j+1]=='F'&&mp[i][j]=='F')
r[i][j]=r[i][j+1];
}
//只有mp[i][j]为'F'才更新ans,只有 mp[i-1][j]为'F'才更新l,r,up;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(i>1&&mp[i][j]=='F'){
if(mp[i-1][j]=='F')
{
l[i][j]=max(l[i-1][j],l[i][j]);
r[i][j]=min(r[i-1][j],r[i][j]);
up[i][j]=up[i-1][j]+1;
}
ans=max(ans,(r[i][j]-l[i][j]+1)*up[i][j]);
}
cout<<ans*3<<endl;
return 0;
}