bzoj 1047[HAOI2007]理想的正方形 - 单调队列

1047: [HAOI2007]理想的正方形

Time Limit: 10 Sec  Memory Limit: 162 MB

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
 
 
先在每行扫一遍,等到以j为结尾的前n个数中的最大最小值
然后在按列扫,表示前n列中的最大最小值
差值最小的就是答案
 
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define LL long long
  6 
  7 using namespace std;
  8 
  9 const int MAXN = 2e3 + 10;
 10 int a, b;
 11 int n;
 12 int map[MAXN][MAXN];
 13 struct queue {
 14     int loc;
 15     int val;
 16 } qb[MAXN], qs[MAXN];
 17 
 18 inline LL read()
 19 {
 20     LL x = 0, w = 1; char ch = 0;
 21     while(ch < '0' || ch > '9') {
 22         if(ch == '-') {
 23             w = -1;
 24         }
 25         ch = getchar();
 26     }
 27     while(ch >= '0' && ch <= '9') {
 28         x = x * 10 + ch - '0';
 29         ch = getchar();
 30     }
 31     return x * w;
 32 }
 33 
 34 int lbg[MAXN][MAXN], lsm[MAXN][MAXN];
 35 
 36 int main()
 37 {
 38     a = read(), b = read(), n = read();
 39     for(int i = 1; i <= a; i++) {
 40         for(int j = 1; j <= b; j++) {
 41             map[i][j] = read();
 42         }
 43     }
 44     for(int i = 1; i <= a; i++) {
 45         int head1 = 0, tail1 = 0;
 46         int head2 = 0, tail2 = 0;
 47         for(int j = 1; j <= b; j++) {
 48             while(head1 < tail1 && qb[head1].loc < j - n + 1) {
 49                 head1++;
 50             }
 51             while(tail1 > head1 && qb[tail1 - 1].val <= map[i][j]) {
 52                 tail1--;
 53             }
 54             qb[tail1].val = map[i][j];
 55             qb[tail1++].loc = j;
 56             lbg[i][j] = qb[head1].val;
 57             while(head2 < tail2 && qs[head2].loc < j - n + 1) {
 58                 head2++;
 59             }
 60             while(tail2 > head2 && qs[tail2 - 1].val >= map[i][j]) {
 61                 tail2--;
 62             }
 63             qs[tail2].val = map[i][j];
 64             qs[tail2++].loc = j;
 65             lsm[i][j] = qs[head2].val;
 66         }
 67     }
 68     int ans = 1e9;
 69     for(int j = n ; j <= b; j++) {
 70         int head1 = 0, tail1 = 0;
 71         int head2 = 0, tail2 = 0;
 72         int big, small;
 73         for(int i = 1; i <= a; i++) {
 74             while(head1 < tail1 && qb[head1].loc < i - n + 1) {
 75                 head1++;
 76             }
 77             while(tail1 > head1 && qb[tail1 - 1].val <= lbg[i][j]) {
 78                 tail1--;
 79             }
 80             qb[tail1].val = lbg[i][j];
 81             qb[tail1++].loc = i;
 82             big = qb[head1].val;
 83             while(head2 < tail2 && qs[head2].loc < i - n + 1) {
 84                 head2++;
 85             }
 86             while(tail2 > head2 && qs[tail2 - 1].val >= lsm[i][j]) {
 87                 tail2--;
 88             }
 89             qs[tail2].val = lsm[i][j];
 90             qs[tail2++].loc = i;
 91             small = qs[head2].val;
 92             if(i >= n) {
 93                 ans = min(ans, big - small);
 94             }
 95         }
 96     }
 97     printf("%d\n", ans);
 98     return 0;
 99 }
100 
101 
102 /*
103 
104 5 4 2
105 
106 1 2 5 6
107 
108 0 17 16 0
109 
110 16 17 2 1
111 
112 2 10 2 1
113 
114 1 2 2 2
115 
116 
117 */
View Code

 

posted @ 2018-03-22 19:26  大财主  阅读(196)  评论(0编辑  收藏  举报