https://acm.hdu.edu.cn/showproblem.php?pid=6957
给定一个 \(n\) 行 \(m\) 列的矩阵,求每个列上不递减的最大面积子矩阵
令 \(sum[i][j]\) 为第 \(i\) 行第 \(j\) 列从上往下以 \(a[i][j]\) 结尾的最长不递减序列长度,枚举每一个 \(sum[i][j]\) 作为列的最长长度, 显然行长度只能延伸到左右第一个小于 \(sum[i][j]\) 的位置之前,用单调栈维护即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e3 + 50; int mp[maxn][maxn]; int sum[maxn][maxn]; int st[maxn], Lmin[maxn], Rmin[maxn], b[maxn]; void getLmin(int a[], int n){//左边第一个小于a[i]的数 int cnt = 0; st[0] = 0; for(int i = 1;i <= n;i++){ while(cnt && a[i] <= a[st[cnt]]) cnt--; Lmin[i] = st[cnt]; st[++cnt] = i; } } void getRmin(int a[], int n){//右边第一个小于a[i]的数 int cnt = 0; st[0] = n + 1; for(int i = n;i >= 1;i--){ while(cnt && a[i] <= a[st[cnt]]) cnt--; Rmin[i] = st[cnt]; st[++cnt] = i; } } int main() { std::ios::sync_with_stdio(false); int t; cin >> t; while(t--){ int n, m; cin >> n >> m; for(int i = 0;i <= n + 1;i++) for(int j = 0;j <= m + 1;j ++){ mp[i][j] = sum[i][j] = 0; } for(int i = 1;i <= n;i++){ for(int j = 1;j <= m;j++){ cin >> mp[i][j]; } } for(int i = 1;i <= n;i++){ for(int j = 1;j <= m;j++){ if(mp[i][j] >= mp[i - 1][j]) sum[i][j] = sum[i - 1][j] + 1; else sum[i][j] = 1; } } int ans = 0; for(int i = 1;i <= n;i++){ for(int j = 1;j <= m;j++){ b[j] = sum[i][j]; } getLmin(b, m); getRmin(b, m); for(int j = 1;j <= m;j++){ ans = max(ans, sum[i][j] * ( (Rmin[j] - 1) - (Lmin[j] + 1) + 1)); } } cout << ans << endl; } return 0; }