bzoj 1047[HAOI2007]理想的正方形 - 单调队列
1047: [HAOI2007]理想的正方形
Time Limit: 10 Sec Memory Limit: 162 MBDescription
有一个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
先在每行扫一遍,等到以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 */