zoukankan      html  css  js  c++  java
  • 【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<=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

    Sample Output

    1

    Solution

    二维单调队列。其实就是先用单调队列压成一维,然后再用单调队列做滑动窗口。

    Code

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cmath>
     5 
     6 #ifdef WIN32
     7     #define LL "%I64d"
     8 #else
     9     #define LL "%lld"
    10 #endif
    11 
    12 #ifdef CT
    13     #define debug(...) printf(__VA_ARGS__)
    14     #define setfile() 
    15 #else
    16     #define debug(...)
    17     #define filename ""
    18     #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout)
    19 #endif
    20 
    21 #define R register
    22 #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
    23 #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    24 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    25 #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    26 #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    27 #define cabs(_x) ((_x) < 0 ? (- (_x)) : (_x))
    28 char B[1 << 15], *S = B, *T = B;
    29 inline int F()
    30 {
    31     R char ch; R int cnt = 0; R bool minus = 0;
    32     while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
    33     ch == '-' ? minus = 1 : cnt = ch - '0';
    34     while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
    35     return minus ? -cnt : cnt;
    36 }
    37 #define maxn 1010
    38 int a[maxn][maxn], mn[maxn][maxn], mx[maxn][maxn], q1[maxn], q2[maxn];
    39 int main()
    40 {
    41 //    setfile();
    42     R int n = F(), m = F(), k = F(), ans = 0x7fffffff;
    43     for (R int i = 1; i <= n; ++i)
    44         for (R int j = 1; j <= m; ++j)
    45             a[i][j] = F();
    46     for (R int j = 1; j <= m; ++j)
    47     {
    48         R int head1 = 1, tail1 = 0;
    49         R int head2 = 1, tail2 = 0;
    50         for (R int i = 1; i < k; ++i)
    51         {
    52             while (head1 <= tail1 && a[q1[tail1]][j] < a[i][j]) --tail1;
    53             while (head2 <= tail2 && a[q2[tail2]][j] > a[i][j]) --tail2;
    54             q1[++tail1] = i;
    55             q2[++tail2] = i;
    56         }
    57         for (R int i = k; i <= n; ++i)
    58         {
    59             while (head1 <= tail1 && q1[head1] + k <= i) ++head1;
    60             while (head2 <= tail2 && q2[head2] + k <= i) ++head2;
    61             while (head1 <= tail1 && a[q1[tail1]][j] < a[i][j]) --tail1;
    62             while (head2 <= tail2 && a[q2[tail2]][j] > a[i][j]) --tail2;
    63             q1[++tail1] = i;
    64             q2[++tail2] = i;
    65             mx[i][j] = a[q1[head1]][j];
    66             mn[i][j] = a[q2[head2]][j];
    67         }
    68     }
    69     for (R int i = k; i <= n; ++i)
    70     {
    71         R int head1 = 1, tail1 = 0;
    72         R int head2 = 1, tail2 = 0;
    73         for (R int j = 1; j < k; ++j)
    74         {
    75             while (head1 <= tail1 && mx[i][q1[tail1]] < mx[i][j]) --tail1;
    76             while (head2 <= tail2 && mn[i][q2[tail2]] > mn[i][j]) --tail2;
    77             q1[++tail1] = j;
    78             q2[++tail2] = j;
    79         }
    80         for (R int j = k; j <= m; ++j)
    81         {
    82             while (head1 <= tail1 && q1[head1] + k <= j) ++head1;
    83             while (head2 <= tail2 && q2[head2] + k <= j) ++head2;
    84             while (head1 <= tail1 && mx[i][q1[tail1]] < mx[i][j]) --tail1;
    85             while (head2 <= tail2 && mn[i][q2[tail2]] > mn[i][j]) --tail2;
    86             q1[++tail1] = j;
    87             q2[++tail2] = j;
    88             cmin(ans, mx[i][q1[head1]] - mn[i][q2[head2]]);
    89         }
    90     }
    91     printf("%d
    ", ans );
    92     return 0;
    93 }
  • 相关阅读:
    LeetCode--Reorder List
    LeetCode--Combination Sum
    LeetCode--Binary Tree Level Order Traversal
    LeetCode--Plus One
    第五届蓝桥杯决赛CC++B组——生物芯片
    第五届蓝桥杯决赛CC++B组——Log大侠
    第五届蓝桥杯决赛CC++B组——出栈次序
    1098 均分纸牌 ——http://codevs.cn/problem/1098/
    1294 全排列——http://codevs.cn/problem/1294/
    1501 二叉树最大宽度和高度——http://codevs.cn/problem/1501/
  • 原文地址:https://www.cnblogs.com/cocottt/p/6618297.html
Copyright © 2011-2022 走看看