City Game UVALive - 3029(悬线法求最大子矩阵)

时间:2023-03-09 03:58:35
City Game UVALive - 3029(悬线法求最大子矩阵)

题意:多组数据(国外题好像都这样),每次n*m矩形,F表示空地,R表示障碍

   求最大子矩阵(悬线法模板)

把每个格子向上延伸的空格看做一条悬线

以le[i][j],re[i][j],up[i][j]分别记录该悬线向左,向右的运动极限以及向上的延伸长度

ans=max(ans,(up[i][j]*(re[i][j]-le[i][j]+1)));

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
#define int long long
#define olinr return
#define _ 0
#define love_nmr 0
#define DB double
inline int read()
{
int x=,f=;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-f;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
return x*f;
}
inline void put(int x)
{
if(x<)
{
x=-x;
putchar('-');
}
if(x>)
put(x/);
putchar(x%+'');
}
int n;
int m;
bool mp[][];
int le[][];
int re[][];
int up[][];
int T;
inline void init()
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
char ch=getchar();
while(!isupper(ch)) ch=getchar();
if(ch=='F')
mp[i][j]=true;
else
mp[i][j]=false;
}
}
inline int work()
{
int ans=;
for(int i=;i<=n;i++)
{
int l=; //当前障碍的位置
int r=m+;
for(int j=;j<=m;j++)
{
if(!mp[i][j]) //有障碍
{
up[i][j]=le[i][j]=;
l=j;
}
else
{
up[i][j]=i==? :up[i-][j]+; //更新
le[i][j]=i==? l+:max(le[i-][j],l+);
}
}
for(int j=m;j>=;j--)
{
if(!mp[i][j])
{
re[i][j]=m+;
r=j;
}
else
{
re[i][j]=i==? r-:min(r-,re[i-][j]); //更新re
ans=max(ans,up[i][j]*(re[i][j]-le[i][j]+)); //更新答案
}
}
}
return ans*; //要求面积*3
}
signed main()
{
T=read();
while(T--)
{
n=read();
m=read();
init();
put(work());
putchar('\n');
}
olinr ~~(^_^)+love_nmr;
}
/*
2
5 6
RFFFFF
FFFFFF
RRRFFF
FFFFFF
FFFFFF
5 5
RRRRR
RRRRR
RRRRR
RRRRR
RRRRR
*/