题目描述
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
输入输出格式
输入格式:
第一行为3个整数,分别表示a,b,n的值
第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
输出格式:
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
输入输出样例
说明
问题规模
(1)矩阵中的所有数都不超过1,000,000,000
(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10
(3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
题意:
给定一个a*b的矩阵,找一个n*n的正方形,使得正方形里最大值和最小值之差最小。
思路:
我们可以预处理出每一个n*n的正方形的最大最小值分别是多少,然后暴力跑一遍找到最小值就可以了。
先处理横着的,用单调队列来维护。刚开始一直写不对,因为队列中应该存的是位置的下标而不是直接存值,因为head++的时候比较的是下标的距离,而我刚开始直接比较了tail和head也就是队列里的元素个数。
然后按照同样的方法,在行处理好的基础上处理列。
发现写单调队列的套路就是。比如我们要建一个存最大值的,那我们应该比较队尾和当前值的关系。
如果队尾比当前值小就要一直tail--
然后删去不满足区间约束的队头的值。
然后每次取的应该是队头的元素。
1 #include <iostream> 2 #include <set> 3 #include <cmath> 4 #include <stdio.h> 5 #include <cstring> 6 #include <algorithm> 7 #include <vector> 8 #include <queue> 9 #include <map> 10 #include <bits/stdc++.h> 11 using namespace std; 12 typedef long long LL; 13 #define inf 0x7f7f7f7f 14 15 const int maxn = 1005; 16 int a, b, n; 17 LL grid[maxn][maxn]; 18 LL row_big[maxn][maxn], col_big[maxn][maxn], row_small[maxn][maxn], col_small[maxn][maxn]; 19 LL que_big[maxn], que_small[maxn]; 20 21 int main() 22 { 23 scanf("%d%d%d", &a, &b, &n); 24 for(int i = 1; i <= a; i++){ 25 for(int j = 1; j <= b; j++){ 26 scanf("%lld", &grid[i][j]); 27 row_big[i][j] = col_big[i][j] = -1; 28 row_small[i][j] = col_small[i][j] = LLONG_MAX; 29 } 30 } 31 32 //cout<<endl; 33 int tail_b = 0, tail_s = 0, head_b = 1, head_s = 1; 34 for(int i = 1; i <= a; i++){ 35 tail_b = tail_s = 0; 36 head_b = head_s = 1; 37 for(int j = 1; j <= b; j++){ 38 //row_big[i][j] = max(que_big[tail_b], grid[i][j]); 39 //cout<<row_big[i][j]<<" "; 40 while(grid[i][que_big[tail_b]] <= grid[i][j] && head_b <= tail_b){ 41 tail_b--; 42 } 43 que_big[++tail_b] = j; 44 while(j - que_big[head_b] >= n){ 45 head_b++; 46 } 47 row_big[i][j] = grid[i][que_big[head_b]]; 48 49 //row_small[i][j] = min(que_small[tail_s], grid[i][j]); 50 while(grid[i][que_small[tail_s]] >= grid[i][j] && head_s <= tail_s){ 51 tail_s--; 52 } 53 que_small[++tail_s] = j; 54 while(j - que_small[head_s] >= n){ 55 head_s++; 56 } 57 row_small[i][j] = grid[i][que_small[head_s]]; 58 } 59 //cout<<endl; 60 } 61 62 /*cout<<endl; 63 for(int i = 1; i <= a; i++){ 64 for(int j = n; j <= b; j++){ 65 cout<<row_big[i][j]<<" "; 66 } 67 cout<<endl; 68 }*/ 69 70 for(int j = 1; j <= b; j++){ 71 tail_b = tail_s = 0; 72 head_b = head_s = 1; 73 for(int i = 1; i <= a; i++){ 74 //col_big[i][j] = max(que_big[tail_b], row_big[i][j]); 75 while(row_big[que_big[tail_b]][j] <= row_big[i][j] && head_b <= tail_b){ 76 tail_b--; 77 } 78 que_big[++tail_b] = i; 79 while(i - que_big[head_b] >= n){ 80 head_b++; 81 } 82 col_big[i][j] = row_big[que_big[head_b]][j]; 83 84 //col_small[i][j] = min(que_small[tail_s], row_small[i][j]); 85 while(row_small[que_small[tail_s]][j] >= row_small[i][j] && head_s <= tail_s){ 86 tail_s--; 87 } 88 que_small[++tail_s] = i; 89 while(i - que_small[head_s] >= n){ 90 head_s++; 91 } 92 col_small[i][j] = row_small[que_small[head_s]][j]; 93 } 94 } 95 96 /*cout<<endl; 97 for(int i = n ;i <= a; i++){ 98 for(int j = n; j <= b; j++){ 99 cout<<col_big[i][j]<<" "; 100 } 101 cout<<endl; 102 }*/ 103 104 LL ans = LLONG_MAX; 105 for(int i = n; i <= a; i++){ 106 for(int j = n; j <= b; j++){ 107 ans = min(ans, col_big[i][j] - col_small[i][j]); 108 } 109 } 110 printf("%lld ", ans); 111 return 0; 112 }