题目来源:BZOJ 1047
思路:
用二维单调队列维护二维数组的最大值和最小值,之后直接查询。
具体的来说,先用单调队列维护每一行的值,再维护每一列的值。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
inline int gt(){
char c = ' ';
int num = 0, op = 1, ok = 0;
while(1){
c = getchar();
if(c == '-') op = -1;
if(c <= '9' && c >= '0') num = num * 10 + c - '0', ok = 1;
else if(ok) return op * num;
}
}
int a1[1010][1010], a2[1010][1010], a3[1010][1010];
int a4[1010][1010], a5[1010][1010];
int a, b, n, res = 2e9;
int q1[1010], l, r;
int main(){
scanf("%d%d%d", &a, &b, &n);
for(int i = 1; i <= a; i ++)
for(int j = 1; j <= b; j ++)
a1[i][j] = gt();
for(int i = 1; i <= a; i ++){
l = 1, r = 0;
for(int j = 1; j <= b; j ++){
while(r >= l && j - q1[l] >= n) l ++;
while(r >= l && a1[i][j] >= a1[i][q1[r]]) r --;
q1[++r] = j;
a2[i][j] = a1[i][q1[l]];
}
l = 1, r = 0;
for(int j = 1; j <= b; j ++){
while(r >= l && j - q1[l] >= n) l ++;
while(r >= l && a1[i][j] <= a1[i][q1[r]]) r --;
q1[++r] = j;
a3[i][j] = a1[i][q1[l]];
}
}
for(int i = 1; i <= b; i ++){
l = 1, r = 0;
for(int j = 1; j <= a; j ++){
while(r >= l && j - q1[l] >= n) l ++;
while(r >= l && a2[j][i] >= a2[q1[r]][i]) r --;
q1[++r] = j;
a4[j][i] = a2[q1[l]][i];
}
l = 1, r = 0;
for(int j = 1; j <= a; j ++){
while(r >= l && j - q1[l] >= n) l ++;
while(r >= l && a3[j][i] <= a3[q1[r]][i]) r --;
q1[++r] = j;
a5[j][i] = a3[q1[l]][i];
}
}
for(int i = n; i <= a; i ++)
for(int j = n; j <= b; j ++)
if(a4[i][j] - a5[i][j] < res) res = a4[i][j] - a5[i][j];
printf("%d", res);
return 0;
}