【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

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 }

 

posted @ 2017-03-25 20:20  cot  阅读(189)  评论(0编辑  收藏  举报