Description
给出一个 n×m 的矩阵,求一个最大子矩阵,使得矩阵中的权值和大于0。输出最大子矩阵的面积。
Solution
枚举上界和下界,中间的一段压成一个序列。我们设 si 表示序列 [1,i] 的权值和。
如果 i<j<k(si<sj<sk) ,显然 j 是冗余的。
那么我们找出单调下降的
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 301
#define ll long long
#define inf 1000000000ll
using namespace std;
ll a[N][N],b[N][N];
ll sum(int x1,int y1,int x2,int y2)
{
return b[x2][y2]-b[x2][y1-1]-b[x1-1][y2]+b[x1-1][y1-1];
}
int n,m;
ll s[N];
int dl[N];
ll qq;
int main()
{
freopen("max.in","r",stdin);
freopen("max.out","w",stdout);
cin>>n>>m;
fo(i,1,n)
fo(j,1,m)
{
scanf("%lld",&a[i][j]);
b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+a[i][j];
}
int ans=0;
fo(u,1,n)
fo(d,u,n)
{
int tot=0;
s[0]=inf;
fo(i,1,m)
{
ll qq=sum(u,1,d,i);
s[i]=qq;
if(s[dl[tot]]>qq) dl[++tot]=i;
}
int j=tot;
fd(i,m,1)
{
while(dl[j]>=i) j--;
if(s[i]>0)
{
ans=max(ans,(d-u+1)*i);
break;
}
while(s[dl[j]]<s[i] && j) j--;
j++;
if(s[dl[j]]<s[i] && dl[j]<i) ans=max(ans,(d-u+1)*(i-dl[j]));
}
}
cout<<ans;
}