• BZOJ 1047 [HAOI2007]理想的正方形


    1047: [HAOI2007]理想的正方形

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2054  Solved: 1091
    [Submit][Status][Discuss]

    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<=100

    Source

    题解:太神了,膜郑爷%%%

    首先看数据范围,很显然要求线性算法,那就是说只能扫一次喽,那就是说要O(1)维护喽,那就是说要敲单调队列喽。。。

    既然要写moque,就要着重考虑一下啥时候该删除了。首先把窝萌的查询的框分成4部分:

    假设窝萌的小正方形从左上角往下动,那么很显然1区域对于两个方向只是添加,2区域对于y方向是增加,对于x方向是维护,3区域对于x方向是增加,对于y方向是维护,4区域对于两个方向都是维护。

    那就好办呀,对于不同的部分用不同的办法维护不就好了。。。。

    注意这里有个细节:比如窝萌维护1区域的时候一定是1~n-1!!!为啥?因为i=n的时候就需要开始回答了!

    然后说一下单调队列:窝萌还需要记录一下进队的时间,用来维护pop操作。然后就码就行了。。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<stack>
     6 #include<queue>
     7 #include<cstring>
     8 #define PAU putchar(' ')
     9 #define ENT putchar('
    ')
    10 using namespace std;
    11 const int maxn=1000+10,inf=-1u>>1;
    12 struct moque{
    13     int a1[1001],t1[1001],a2[1001],t2[1001];
    14     int st1,ed1,st2,ed2;
    15     moque(){st1=1;ed1=0;st2=1;ed2=0;}
    16     void pushmi(int x,int t){
    17         while((st1<=ed1)&&(x<=a1[ed1]))ed1--;ed1++;a1[ed1]=x;t1[ed1]=t;return;
    18     }
    19     void pushmx(int x,int t){
    20         while((st2<=ed2)&&(x>=a2[ed2]))ed2--;ed2++;a2[ed2]=x;t2[ed2]=t;return;
    21     }
    22     void pop(int t){
    23         if(t1[st1]==t)st1++;if(t2[st2]==t)st2++;return;
    24     }
    25     int qmin(){return a1[st1];}
    26     int qmax(){return a2[st2];}
    27 }qx[maxn],qy[maxn];
    28 int a,b,n,A[maxn][maxn];
    29 inline int read(){
    30     int x=0,sig=1;char ch=getchar();
    31     for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=0;
    32     for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
    33     return sig?x:-x;
    34 }
    35 inline void write(int x){
    36     if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
    37     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
    38     for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
    39 }
    40 int main(){
    41     a=read();b=read();n=read();
    42     for(int i=1;i<=a;i++)for(int j=1;j<=b;j++)A[i][j]=read();
    43     for(int i=1;i<n;i++){
    44         for(int j=1;j<n;j++)qx[i].pushmi(A[i][j],j),qx[i].pushmx(A[i][j],j);
    45         for(int j=n;j<=b;j++){
    46             qx[i].pushmi(A[i][j],j);qx[i].pushmx(A[i][j],j);
    47             qy[j].pushmi(qx[i].qmin(),i);qy[j].pushmx(qx[i].qmax(),i);
    48             qx[i].pop(j-n+1);
    49         }
    50     }int ans=inf;
    51     for(int i=n;i<=a;i++){
    52         for(int j=1;j<n;j++)qx[i].pushmi(A[i][j],j),qx[i].pushmx(A[i][j],j);
    53         for(int j=n;j<=b;j++){
    54             qx[i].pushmi(A[i][j],j);qx[i].pushmx(A[i][j],j);
    55             qy[j].pushmi(qx[i].qmin(),i);qy[j].pushmx(qx[i].qmax(),i);
    56             ans=min(ans,qy[j].qmax()-qy[j].qmin());
    57             qx[i].pop(j-n+1);qy[j].pop(i-n+1);
    58         }
    59     }write(ans);
    60     return 0;
    61 }
  • 相关阅读:
    make 实例 一 3463
    python3 中对arrow库的总结(转发)
    impala 导出CSV 或excel
    设置虚拟机IP
    centos7 tomcat9
    eclipse 创建普通maven项目
    java log4j日志配置
    java运行jar命令提示没有主清单属性
    Java 读取 .properties 配置文件
    python 机器学习多项式回归
  • 原文地址:https://www.cnblogs.com/chxer/p/4727243.html
Copyright © 2020-2023  润新知