Given a matrix of n rows and m columns,find the largest area submatrix which is non decreasing on each column
Input
The first line contains an integer T(1≤T≤10)
representing the number of test cases.
For each test case, the first line contains two integers n,m(1≤n,m≤2∗103)representing the size of the matrix
the next n line followed. the i-th line contains m integers vij(1≤vij≤5∗103)representing the value of matrix
It is guaranteed that there are no more than 2 testcases with n∗m>10000
Output
For each test case, print a integer representing the Maximal submatrix
Sample Input
1 2 3 1 2 4 2 3 3
Sample Output
4
题目大意
求矩阵的最大面积 其中必须要满足a[i][j]>=a[i-1][j];
思路
1将数组转换为01数组 然后用悬线法计算面积
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=2e3+10;
int t,n,m;
int mp[maxn][maxn];
int le[maxn][maxn];
int r[maxn][maxn];
int h[maxn][maxn];
int mi(int x,int y)
{
if(x<y)
return x;
else return y;
}
int ma(int x,int y)
{
if(x<y)
return y;
else return x;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>m;
memset(le,0,sizeof(le));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
le[0][j]=0;
scanf("%d",&mp[i][j]);
if(i!=1)
if(mp[i][j]>=mp[i-1][j])
{
le[i][j]=1;
}
//else le[i][j]=1;
}
}
memset(mp,0,sizeof(mp));
memset(h,0,sizeof(h));
memset(r,0,sizeof(r));
int ans=m;
int L=1e9,R=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(le[i][j]==1)
{
L=mi(L,j);
}
else L=1e9;
mp[i][j]=L;
}
for(int j=m;j>=1;j--)
{
if(le[i][j]==1)
{
R=ma(R,j);
}
else R=0;
r[i][j]=R;
}
for(int j=1;j<=m;j++)
{
if(le[i-1][j]==1)
{
h[i][j]=h[i-1][j]+1;
mp[i][j]=ma(mp[i-1][j],mp[i][j]);
r[i][j]=mi(r[i-1][j],r[i][j]);
}
else h[i][j]=1;
if(le[i][j]==1)
{
ans=max(ans,(r[i][j]-mp[i][j]+1)*(h[i][j]+1));
}
}
}
cout<<ans<<endl;
}
return 0;
}
2 逐行 用单调栈计算最大面积
#include<bits/stdc++.h>
using namespace std;
int t;
int n,m,k;
int top;
const int maxn =2e3+10;
int h[maxn],b[maxn];
int a[maxn][maxn];
int main()
{
cin>>t;
while(t--)
{
stack<int >s;
int ans=0;
memset(h,0,sizeof(h));
memset(b,0,sizeof(b));
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]>=a[i-1][j])
{
h[j]++;
}
else h[j]=1;
b[j]=h[j];
}
b[m+1]=-1;
for(int j=1;j<=m+1;j++)
{
if(s.empty()||b[s.top()]<=b[j])
{
s.push(j);
continue;
}
while(!s.empty()&&b[s.top()]>b[j])
{
top=s.top();
s.pop();
int tmp=(j-top)*b[top];
ans=max(ans,tmp);
}
s.push(top);
b[top]=b[j];//将第一个 大于j的值的位置(top)再放进去 但是值要改变
}
}
cout<<ans<<endl;
}
return 0;
}