【BZOJ1047】[HAOI2007]理想的正方形
Description
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。
Input
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000
Output
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
Sample Input
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
Sample Output
1
Solution
二维单调队列。其实就是先用单调队列压成一维,然后再用单调队列做滑动窗口。
Code
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 6 #ifdef WIN32 7 #define LL "%I64d" 8 #else 9 #define LL "%lld" 10 #endif 11 12 #ifdef CT 13 #define debug(...) printf(__VA_ARGS__) 14 #define setfile() 15 #else 16 #define debug(...) 17 #define filename "" 18 #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout) 19 #endif 20 21 #define R register 22 #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) 23 #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) 24 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) 25 #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) 26 #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) 27 #define cabs(_x) ((_x) < 0 ? (- (_x)) : (_x)) 28 char B[1 << 15], *S = B, *T = B; 29 inline int F() 30 { 31 R char ch; R int cnt = 0; R bool minus = 0; 32 while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; 33 ch == '-' ? minus = 1 : cnt = ch - '0'; 34 while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; 35 return minus ? -cnt : cnt; 36 } 37 #define maxn 1010 38 int a[maxn][maxn], mn[maxn][maxn], mx[maxn][maxn], q1[maxn], q2[maxn]; 39 int main() 40 { 41 // setfile(); 42 R int n = F(), m = F(), k = F(), ans = 0x7fffffff; 43 for (R int i = 1; i <= n; ++i) 44 for (R int j = 1; j <= m; ++j) 45 a[i][j] = F(); 46 for (R int j = 1; j <= m; ++j) 47 { 48 R int head1 = 1, tail1 = 0; 49 R int head2 = 1, tail2 = 0; 50 for (R int i = 1; i < k; ++i) 51 { 52 while (head1 <= tail1 && a[q1[tail1]][j] < a[i][j]) --tail1; 53 while (head2 <= tail2 && a[q2[tail2]][j] > a[i][j]) --tail2; 54 q1[++tail1] = i; 55 q2[++tail2] = i; 56 } 57 for (R int i = k; i <= n; ++i) 58 { 59 while (head1 <= tail1 && q1[head1] + k <= i) ++head1; 60 while (head2 <= tail2 && q2[head2] + k <= i) ++head2; 61 while (head1 <= tail1 && a[q1[tail1]][j] < a[i][j]) --tail1; 62 while (head2 <= tail2 && a[q2[tail2]][j] > a[i][j]) --tail2; 63 q1[++tail1] = i; 64 q2[++tail2] = i; 65 mx[i][j] = a[q1[head1]][j]; 66 mn[i][j] = a[q2[head2]][j]; 67 } 68 } 69 for (R int i = k; i <= n; ++i) 70 { 71 R int head1 = 1, tail1 = 0; 72 R int head2 = 1, tail2 = 0; 73 for (R int j = 1; j < k; ++j) 74 { 75 while (head1 <= tail1 && mx[i][q1[tail1]] < mx[i][j]) --tail1; 76 while (head2 <= tail2 && mn[i][q2[tail2]] > mn[i][j]) --tail2; 77 q1[++tail1] = j; 78 q2[++tail2] = j; 79 } 80 for (R int j = k; j <= m; ++j) 81 { 82 while (head1 <= tail1 && q1[head1] + k <= j) ++head1; 83 while (head2 <= tail2 && q2[head2] + k <= j) ++head2; 84 while (head1 <= tail1 && mx[i][q1[tail1]] < mx[i][j]) --tail1; 85 while (head2 <= tail2 && mn[i][q2[tail2]] > mn[i][j]) --tail2; 86 q1[++tail1] = j; 87 q2[++tail2] = j; 88 cmin(ans, mx[i][q1[head1]] - mn[i][q2[head2]]); 89 } 90 } 91 printf("%d\n", ans ); 92 return 0; 93 }