题意
其实就是BZOJ3039 不过没权限号(粗鄙之语)
同时也是洛谷4147
就是求最大子矩阵然后*3
思路
悬线法
有个博客讲的不错https://blog.csdn.net/u012288458/article/details/48197727
GREED-VI大佬之前也讲过,友链一下https://www.cnblogs.com/GREED-VI/p/9887399.html (他说的其实是悬线法,扫描线和这个不一样的吧)
代码
水水水
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define N 1005 using namespace std; int n,m; int ans; int up[N][N],L[N][N],R[N][N]; pair<int,int> st[N]; bool v[N][N],f_fall; void init() { char ch; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>ch; v[i][j]=(ch=='F'?1:0); if(v[i][j]) f_fall=1; } } void solve() { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(!v[i][j]) up[i][j]=0; else up[i][j]=up[i-1][j]+1; for (int i=1;i<=n;i++) { int top=0; st[++top]=make_pair(-1,0); for (int j=1;j<=m;j++) { while (up[i][j]<=st[top].first) top--; L[i][j]=j-st[top].second-1; st[++top]=make_pair(up[i][j],j); } } for (int i=1;i<=n;i++) { int top=0; st[++top]=make_pair(-1,m+1); for (int j=m;j>=1;j--) { while (up[i][j]<=st[top].first) top--; R[i][j]=st[top].second-j-1; st[++top]=make_pair(up[i][j],j); } } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ans=max(ans,(L[i][j]+R[i][j]+1)*up[i][j]); ans*=3; } int main() { //freopen("cpp.in","r",stdin); //freopen("cpp.out","w",stdout); int Q;scanf("%d",&Q); while(Q--) { f_fall=0; init(); if(f_fall==0) printf("0 "); else{ solve(); printf("%d ",ans); ans=0; memset(v,0,sizeof(v)); memset(up,0,sizeof(up)); memset(L,0,sizeof(L)); memset(R,0,sizeof(R)); memset(st,0,sizeof(st)); } } return 0; }