题意:给出一个n*m的整数矩阵A,问竖直方向上不减的最大子矩阵的面积是多少
解法:悬线法/单调栈
我们先将原矩阵化为另一个矩阵H,H[i][j]表示第i行第j列的高度(竖直方向上以A[i][j]为最后一个元素的连续不递减序列的长度),这题就变成了以第i行为底边,j处有一个高为H[i][j]的矩形,求这行的矩形构成的最大矩形的面积,然后求所有这些矩形的最大面积
悬线法/单调栈可以O(m)时间求一行的所有可构成矩形的最大面积,n行的时间为O(nm),不懂悬线法的戳这里:悬线法
AcCode
#include<iostream>
#include<algorithm>
#define in std::cin>>
#define out std::cout<<
const int N = 2e3 + 10;
int arr[N][N];
int val[N][N];
int L[N][N];
int R[N][N];
inline int max(int a, int b) { return (a > b) ? a : b; }
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int t; in t;
while (t--) {
int n; in n;
int m; in m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
in arr[i][j];
val[i][j] = 1;
if (arr[i][j] >= arr[i - 1][j]) val[i][j] = val[i - 1][j] + 1;
L[i][j] = R[i][j] = j;
}
}
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= m; j++) {
while (L[i][j] > 1 && val[i][j] <= val[i][L[i][j] - 1]) L[i][j] = L[i][L[i][j] - 1];//L[i][j]向左可以到的地方
}
}
for (int i = 2; i <= n; i++) {
for (int j = m; j; j--) {
while (R[i][j] < m && val[i][j] <= val[i][R[i][j] + 1]) R[i][j] = R[i][R[i][j] + 1];
}
}
int ans = m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
ans = max(ans, val[i][j] * (R[i][j] - L[i][j] + 1));
}
}
out ans << "\n";
}
}