(赛场上想到了用单调栈,但是单调栈写错了没能过这题)

我们用sum[i][j]记录包含第i行第j列元素的当前最长不递减序列长度

如样例

1 2 4

2 3 3

用sum[i][j]记录

1 1 1

2 2 1

粗看这么记录好像没有什么作用

但单独抽出一行来看,把sum当作深度,我们发现这个问题转化为了一个经典的单调栈求最大矩形面积的问题

于是每一行使用单调栈判定

复杂度(Tnm),只有最多两组数据n*m>10000,显然是满足题目条件的

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
using namespace std;

int T;
int n,m;
int sum[3020][3020];
int a[3020][3020];
int maxn=0;
int l[3020];
int r[3020];

int main(){
    scanf("%d",&T);
    while(T--)
    {
        maxn=0;
        scanf("%d%d",&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])
                {
                    sum[i][j]=sum[i-1][j]+1;
                }
                else sum[i][j]=1;
                //printf("%d ",sum[i][j]);
            }
            sum[i][m+1]=0;
            //cout<<endl;
        }
        for(int i=1;i<=n;i++)
        {
            memset(l,0,sizeof(l));
            memset(r,0,sizeof(r));
            stack<int>q;
            q.push(0);
            for(int j=1;j<=m+1;j++)
            {
                while(!q.empty()&&sum[i][q.top()]>=sum[i][j])
                {
                    q.pop();
                }
                if(j==m+1)break;
                l[j]=q.top()+1;
                q.push(j);
            }
            while(!q.empty())q.pop();
            q.push(m+1);
            for(int j=m;j>=0;j--)
            {
                while(!q.empty()&&sum[i][q.top()]>=sum[i][j])
                {
                    q.pop();
                }
                if(j==0)break;
                r[j]=q.top()-1;
                q.push(j);
            }
            for(int j=1;j<=m;j++)
            {
                int tot=sum[i][j]*(r[j]-l[j]+1);
                //cout<<tot<<endl;
                maxn=max(maxn,tot);
            }
        }
        printf("%d\n",maxn);
    }
    return 0;
}