题目链接:点我啊╭(╯^╰)╮
题目大意:
给一个
n
∗
n
n*n
n∗n 的矩阵
求最大子矩阵面积
子矩阵里的最大值
−
-
− 最小值小于等于
M
M
M
解题思路:
看到最大子矩阵就用单调队列
枚举上下边界,预处理该上下边界里每一列的最大最小值
然后枚举每一列
发现右边界往右移的过程中,左边界只会往右移
所以这里套个尺取法即可
左边界移动时,要用两个单调队列维护滑动窗口的最大最小值
时间复杂度:
O
(
n
3
)
O(n^3)
O(n3)
核心:尺取法 + 单调队列
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const ll mod = 1e9 + 7;
const int maxn = 5e2 + 10;
int T, n, m, ans;
int a[maxn][maxn];
int mx[maxn], mi[maxn];
int qmx[maxn], qmi[maxn];
int main() {
scanf("%d", &T);
while(T--){
ans = 0;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d", &a[i][j]);
for(int up=1; up<=n; up++){
for(int i=1; i<=n; i++) mx[i] = 0;
for(int i=1; i<=n; i++) mi[i] = 1e5 + 10;
for(int dn=up; dn<=n; dn++){
for(int i=1; i<=n; i++) mx[i] = max(mx[i], a[dn][i]);
for(int i=1; i<=n; i++) mi[i] = min(mi[i], a[dn][i]);
int head1 = 1, tail1 = 0;
int head2 = 1, tail2 = 0;
int k = 1;
for(int i=1; i<=n; i++){
while(head1<=tail1 && mx[i]>mx[qmx[tail1]]) tail1--;
while(head2<=tail2 && mi[i]<mi[qmi[tail2]]) tail2--;
qmx[++tail1] = i;
qmi[++tail2] = i;
while(mx[qmx[head1]]-mi[qmi[head2]]>m && k<=i){
if(qmx[head1]==k) head1++;
if(qmi[head2]==k) head2++;
k++;
}
if(k <= i) ans = max(ans, (i-k+1)*(dn-up+1));
}
}
}
printf("%d\n", ans);
}
}