洛谷P2216 理想的正方形

题目描述

有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

输入输出格式

输入格式:

 

第一行为3个整数,分别表示a,b,n的值

第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。

 

输出格式:

 

仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

 

输入输出样例

输入样例#1: 复制
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
输出样例#1: 复制
1

说明

问题规模

(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\n", ans);
111     return 0;
112 }

 

posted @ 2018-10-31 18:54  wyboooo  阅读(182)  评论(0编辑  收藏  举报