zoukankan      html  css  js  c++  java
  • BZOJ 1047 理想的正方形

    Description

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

    Input

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

    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

    问题规模

    (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<=10

    Source

    一个典型的单调队列dp,枚举矩阵左端,下端利用单调队列一路扫过,复杂度O(n2)。

    我的代码不知道为什么神慢无比,险些TLE,仅供参考。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<iostream>
     4 using namespace std;
     5 
     6 #define inf (2000000000)
     7 #define maxn 1010
     8 int a,b,n,s[maxn][maxn],ans = inf;
     9 
    10 inline int read()
    11 {
    12     int x=0,f=1;char ch=getchar();
    13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    14     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    15     return x*f;
    16 }
    17 
    18 struct node { int h,key; }q1[maxn*maxn],q2[maxn*maxn];
    19 
    20 inline void work()
    21 {
    22     int h1,t1,h2,t2;
    23     int lef,rig,up,down;
    24     for (lef = 1;lef+n-1 <= b;++lef)
    25     {
    26         rig = lef+n-1; up = 1; down = n;
    27         h1 = t1 = h2 = t2 = 0;
    28         for (int i = up;i <= down;++i)
    29             for (int j = lef;j <= rig;++j)
    30             {
    31                 while (h1 < t1 && s[i][j] <= q1[t1].key) --t1;
    32                 q1[++t1] = (node){i,s[i][j]};
    33                 while (h2 < t2 && s[i][j] >= q2[t2].key) --t2;
    34                 q2[++t2] = (node){i,s[i][j]};
    35             }
    36         ans = min(ans,q2[h2+1].key - q1[h1+1].key);
    37         for (++down,++up;down <= a;++down,++up)
    38         {
    39             while (q1[h1+1].h < up) ++h1;
    40             while (q2[h2+1].h < up) ++h2;
    41             for (int i = lef;i <= rig;++i)
    42             {
    43                 while (h1 < t1 && s[down][i] <= q1[t1].key) --t1;
    44                 q1[++t1] = (node){down,s[down][i]};
    45                 while (h2 < t2 && s[down][i] >= q2[t2].key) --t2;
    46                 q2[++t2] = (node){down,s[down][i]};
    47             }
    48             ans = min(ans,q2[h2+1].key - q1[h1+1].key);
    49         }
    50     }
    51 }
    52 
    53 int main()
    54 {
    55     a = read(); b = read(); n = read();
    56     for (int i = 1;i <= a;++i) for (int j = 1;j <= b;++j) s[i][j] = read();
    57     work();
    58     printf("%d",ans);
    59     return 0;
    60 }
    View Code
  • 相关阅读:
    FullCalendar日历插件说明文档
    Git忽略规则及.gitignore规则不生效的解决办法
    学习git config配置文件
    拼接最长回文串
    Gildong owns a bulgogi restaurant
    前m大的数
    求水洼(dfs)
    循环数组的最大子段和
    求叶子节点
    周期
  • 原文地址:https://www.cnblogs.com/mmlz/p/4294077.html
Copyright © 2011-2022 走看看