题目:https://ac.nowcoder.com/acm/contest/883/F
题意:找最大的矩阵,满足矩阵内最大值最小值差值不超过m。
思路:n<=500,可以O(n^3)先确定上、下、右边界,问题转化为一维数组中O(1)找出最远左边界。记录以当前坐标为右边界时的最大值和最小值,两个单调队列维护最大值递减,最小值递增,每次找队尾的满足条件的一对最大值和最小值,更新答案即可。
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 502;
const int inf = 1e9;
int t, n, m, a[maxn][maxn], l1, r1, l2, r2, q1[maxn], q2[maxn], p, mx[maxn], mn[maxn];
int main()
{
scanf("%d", &t);
while(t--){
int 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 u=1; u<=n; u++){//up
memset(mx, 0, sizeof mx); memset(mn, 0x3f, sizeof mn);
for(int d=u; d<=n; d++){//down
l1 = r1 = l2 = r2 = 0;
for(int r=1,p=0; r<=n; r++){//right
mx[r]=max(mx[r], a[d][r]), mn[r]=min(mn[r], a[d][r]);
while(l1<r1&&mx[q1[r1-1]]<mx[r]) r1--;
while(l2<r2&&mn[q2[r2-1]]>mn[r]) r2--;
q1[r1++] = q2[r2++] = r;
while(l1<r1&&l2<r2&&mx[q1[l1]]-mn[q2[l2]]>m)
p = q1[l1]<q2[l2] ? q1[l1++] : q2[l2++];
ans = max(ans, (d-u+1)*(r-p));
}
}
}
cout << ans << endl;
}
}