悬线法(p4147洛谷)

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;
}
posted @ 2022-01-19 18:10  wzx_believer  阅读(29)  评论(0编辑  收藏  举报