传送门
首先,我们应该先算出每一行每N个数的最大值,保存在mx里面。
同样的再处理出mn(最小值)。
然后处理出mx数组中每一列每N个数的最大值,保存在MX中。
同样的再处理出MN(最小值)。
(以上的处理用单调队列最方便。)
然后再n²处理出MX-MN的最小值就行了
这道题我的代码略丑……
/**************************************************************
Problem: 1047
User: geng4512
Language: C++
Result: Accepted
Time:2284 ms
Memory:20536 kb
****************************************************************/
#include<cstdio>
#define min(a,b) (a)<(b)?(a):(b)
const int MAXN = 1000 + 5;
int a, b, n, q[MAXN], mx[MAXN][MAXN], mp[MAXN][MAXN], mn[MAXN][MAXN], MX[MAXN][MAXN], MN[MAXN][MAXN];
int main()
{
scanf("%d%d%d", &a, &b, &n);
for(int i = 1; i <= a; i ++)
for(int j = 1; j <= b; j ++)
scanf("%d", &mp[i][j]);
int l = 0, r = 0;
for(int j = 1; j <= a; j ++) // 处理mx
{
l = 0, r = 0;
for(int i = 1; i <= b; i ++)
{
while(l < r && mp[j][i] > mp[j][q[r-1]]) --r;
while(l < r && q[l] <= i - n) ++l;
q[r++] = i;
mx[j][i] = mp[j][q[l]];
}
}
l = 0, r = 0;
for(int j = 1; j <= a; j ++)// 处理mn
{
l = 0, r = 0;
for(int i = 1; i <= b; i ++)
{
while(l < r && mp[j][i] < mp[j][q[r-1]]) --r;
while(l < r && q[l] <= i - n) ++l;
q[r++] = i;
mn[j][i] = mp[j][q[l]];
}
}
l = 0, r = 0;
for(int j = 1; j <= b; j ++) // 处理MX
{
l = 0, r = 0;
for(int i = 1; i <= a; i ++)
{
while(l < r && mx[i][j] > mx[q[r-1]][j]) --r;
while(l < r && q[l] <= i - n) ++l;
q[r++] = i;
MX[i][j] = mx[q[l]][j];
}
}
l = 0, r = 0;
for(int j = 1; j <= b; j ++) // 处理MN
{
l = 0, r = 0;
for(int i = 1; i <= a; i ++)
{
while(l < r && mn[i][j] < mn[q[r-1]][j]) --r;
while(l < r && q[l] <= i - n) ++l;
q[r++] = i;
MN[i][j] = mn[q[l]][j];
}
}
int ans = 0x3f3f3f3f;
for(int i = n; i <= a; i ++)
for(int j = n; j <= b; j ++)
ans = min(MX[i][j] - MN[i][j], ans);
printf("%d\n", ans);
return 0;
}