• 洛谷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
    ", ans);
    111     return 0;
    112 }
  • 相关阅读:
    【android】string.xml中的一些错误
    【android】【转】class android.media.MediaPlayer
    【android】gallery 循环播放
    【android】使用handler更新UI
    【android】Textview部分字符高亮
    【android】AudioManager音量控制
    【Android】listview选中行字体变大
    整理模拟练习8 第三章 会计电算化的工作环境
    会计电算化模拟试题9
    第二章 会计电算化基本要求
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9885136.html
Copyright © 2020-2023  润新知