原题地址:https://ac.nowcoder.com/acm/contest/883/F
题意:给出一个矩阵,找出一个最大的子矩阵使得矩阵内的最大值和最小值差小于k。
思路:这个题有个一维的版本,也就是HDU 3530
对于上面那个题,我们枚举矩阵的任意两行,我们对这两行的中间的矩阵进行压缩,这样子就将二维的转化为了一位。
对于一维的,维护两个单调队列,一个单调递增,一个单调递减。每次比较队首元素之差,如果大于k,那么就弹出两个队列中队首元素靠左的那个。每次更新面积最大值即可。
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int n, k, T;
int a[505][505];
int q_max[maxn], q_min[maxn];
int l_max, l_min, r_max, r_min;
int mi[505], mx[505];
int main() {
int T;
scanf("%d", &T);
while (T--) {
int ans = 0;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &a[i][j]);
}
}
for (int p = 1; p <= n; p++) {//枚举第1行
for (int k = 1; k <= n; k++) {
mi[k] = INF;
mx[k] = -INF;
}
for (int j = p; j <= n; j++) {//枚举最后一行
for (int k = 1; k <= n; k++) {
mi[k] = min(mi[k], a[j][k]);
mx[k] = max(mx[k], a[j][k]);
}
l_min = l_max = 1;
r_min = r_max = 0;
int tmp = 0;
for (int i = 1; i <= n; i++) {
while (l_max <= r_max && mx[i] > mx[q_max[r_max]]) {
r_max--;
}
while (l_min <= r_min && mi[i] < mi[q_min[r_min]]) {
r_min--;
}
q_max[++r_max] = i;
q_min[++r_min] = i;
while (l_min <= r_min && l_max <= r_max && mx[q_max[l_max]] - mi[q_min[l_min]] > k) {
int x = q_max[l_max];
int y = q_min[l_min];
if (x < y) {//找到靠左的
tmp = q_max[l_max++];
} else {
tmp = q_min[l_min++];
}
}
if (l_min <= r_min && l_max <= r_max) {
ans = max(ans, (j - p + 1) * (i - tmp));
}
}
}
}
printf("%d\n", ans);
}
return 0;
}