2019牛客多校第二场H题(悬线法)

把以前的题补补,用悬线求面积第二大的子矩形。我们先求出最大子矩阵的面积,并记录其行三个方向上的悬线长度。然后排除这个矩形,记得还得特判少一行或者少一列的情况

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int n;
int mat[maxn][maxn],Left[maxn][maxn],Right[maxn][maxn],up[maxn][maxn];

int main()
{
    int T;
    T=1;
    while(T--)
    {
        int m,n;
        cin>>m>>n;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                char ch;
                cin>>ch;
                mat[i][j]=ch=='1'?0:1;
            }
        }
        int ans=0,max2=0,l,r,u,b;
        for(int i=0;i<m;i++)
        {
            int lo=-1,ro=n;
            for(int j=0;j<n;j++)
            {
                if(mat[i][j]==1)
                {
                    up[i][j]=Left[i][j]=0;lo=j;
                }
                else
                {
                    up[i][j]=i==0?1:up[i-1][j]+1;
                    Left[i][j]=i==0?lo+1:max(Left[i-1][j],lo+1);
                }
            }
            for(int j=n-1;j>=0;j--)
            {
                if(mat[i][j]==1)
                {
                    Right[i][j]=n;ro=j;
                }
                else
                {
                    Right[i][j]=i==0?ro-1:min(Right[i-1][j],ro-1);
                    if(ans<(up[i][j]*(Right[i][j]-Left[i][j]+1)))
                    {
                        ans=up[i][j]*(Right[i][j]-Left[i][j]+1);
                        u=up[i][j],l=Left[i][j],r=Right[i][j],b=i;
                     } 
                }
            }
        }
        max2=max(max2,u*(r-l));
        max2=max(max2,(u-1)*(r-l+1)); 
        for(int i=0;i<m;i++)
        {
            int lo=-1,ro=n;
            for(int j=0;j<n;j++)
            {
                if(mat[i][j]==1)
                {
                    up[i][j]=Left[i][j]=0;lo=j;
                }
                else
                {
                    up[i][j]=i==0?1:up[i-1][j]+1;
                    Left[i][j]=i==0?lo+1:max(Left[i-1][j],lo+1);
                }
            }
            for(int j=n-1;j>=0;j--)
            {
                if(mat[i][j]==1)
                {
                    Right[i][j]=n;ro=j;
                }
                else
                {
                    Right[i][j]=i==0?ro-1:min(Right[i-1][j],ro-1);    
                    if(u==up[i][j]&&l==Left[i][j]&&r==Right[i][j]&&b==i)
                    continue;
                    if(max2<(up[i][j]*(Right[i][j]-Left[i][j]+1)))
                    {
                        max2=up[i][j]*(Right[i][j]-Left[i][j]+1);
                        
                     } 
                }
            }
        }
        cout<<max2<<"\n";
     } 
    return 0;
}

 

posted @ 2019-10-14 23:32  hh13579  阅读(129)  评论(0编辑  收藏  举报