2021HDU多校训练赛(1)1008(HDU6957)Maximal submatrix
链接:
题目大意:
给你一个矩阵,输出最大的列不下降的子矩阵。
题解:
题目经预处理每个点的最长不下降序列之后可以转化为求直方图中的最大矩形
(该图片源链接来自@ojzha_gcx 原文链接)
求直方图最大矩形可以使用单调栈前后跑两次,也可以使用悬点法dp,代码如下
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=4000;
const int inf=0x3f3f3f3f;
int a[N][N],k[N][N],ans=0,maxx=0;
void solve()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]),k[i][j]=1;
for(int i=n-1;i>=1;i--) for(int j=1;j<=m;j++) if(a[i][j]<=a[i+1][j]) k[i][j]=k[i+1][j]+1;
// for(int i=1;i<=n;i++){
// for(int j=1;j<=m;j++) cout<<k[i][j]<<" ";
// cout<<endl;
// }
int l[N],r[N];
int ans=0;
for(int i=1;i<=n;i++)
{
k[i][m+1]=0;
stack<pair<int,int> > s;
for(int j=1;j<=m+1;j++)
{
int w=0;
while(s.size()&&k[i][j] <= s.top().first){
w+=s.top().second;
ans=max(ans,s.top().first*w);
s.pop();
}
s.push({k[i][j],1+w});
}
}
cout<<ans<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
这里有一个问题,由于杭电的oj跑的实在是太慢了。4e7 读入跑4000ms的题竟然会直接TLE,所以这里能用scanf就尽量用scanf。