• [BZOJ1047] [HAOI2007] 理想的正方形 (单调队列)


    Description

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

    Input

      第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
    行相邻两数之间用一空格分隔。
    100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100

    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

    HINT

    Source

    Solution

      开始想用二维$ST$表,查了题解发现有复杂度更低的,,,

      由于限定了矩阵长和宽都为$n$,于是就有了滑动窗口最大最小值的感觉

      将每个点开始向左$n$个点的最大最小值算出来,对行使用单调队列求最值

      接着将每个点作为右下角的$n*n$的矩阵的最大最小值求出来,使用刚才算出来的值,对列使用单调队列求最值

      这样我们就算出来了每一个点对应的矩形的最大值减最小值

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int q[1005], c[1005][1005], r[4][1005][1005];
     4 int main()
     5 {
     6     int a, b, n, front, back, ans = 1000000000;
     7     scanf("%d%d%d", &a, &b, &n);
     8     for(int i = 1; i <= a; ++i)
     9         for(int j = 1; j <= b; ++j)
    10             scanf("%d", &c[i][j]);
    11     for(int i = 1; i <= a; ++i)
    12     {
    13         front = back = 0;
    14         for(int j = 1; j <= b; ++j)
    15         {
    16             if(front != back && j - q[front + 1] == n)
    17                 ++front;
    18             while(front != back && c[i][j] <= c[i][q[back]])
    19                 --back;
    20             q[++back] = j;
    21             r[0][i][j] = c[i][q[front + 1]];
    22         }
    23         front = back = 0;
    24         for(int j = 1; j <= b; ++j)
    25         {
    26             if(front != back && j - q[front + 1] == n)
    27                 ++front;
    28             while(front != back && c[i][j] >= c[i][q[back]])
    29                 --back;
    30             q[++back] = j;
    31             r[1][i][j] = c[i][q[front + 1]];
    32         }
    33     }
    34     for(int j = n; j <= b; ++j)
    35     {
    36         front = back = 0;
    37         for(int i = 1; i <= a; ++i)
    38         {
    39             if(front != back && i - q[front + 1] == n)
    40                 ++front;
    41             while(front != back && r[0][i][j] <= r[0][q[back]][j])
    42                 --back;
    43             q[++back] = i;
    44             r[2][i][j] = r[0][q[front + 1]][j];
    45         }
    46         front = back = 0;
    47         for(int i = 1; i <= a; ++i)
    48         {
    49             if(front != back && i - q[front + 1] == n)
    50                 ++front;
    51             while(front != back && r[1][i][j] >= r[1][q[back]][j])
    52                 --back;
    53             q[++back] = i;
    54             r[3][i][j] = r[1][q[front + 1]][j];
    55         }
    56     }
    57     for(int i = n; i <= a; ++i)
    58         for(int j = n; j <= b; ++j)
    59             ans = min(ans, r[3][i][j] - r[2][i][j]);
    60     printf("%d
    ", ans);
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    JSP 使用
    Spring MVC 读取静态资源时404错误
    Java及Android开发环境搭建
    堆和栈的区别
    fork Bomb
    Hbase Shell常用命令
    CSS选择器的系统介绍
    JavaScript中的位置坐标
    JavaScript事件
    战略型、战术型
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5667932.html
Copyright © 2020-2023  润新知