• bzoj1047 理想的正方形


    Description

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

    Input

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

    Output

    仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

    水平方向用单调队列扫一次得出所有1*n区域的最大值和最小值

    竖直方向再用单调队列扫一次上一部记录的最大值和最小值得出所有n*n区域的最大值和最小值

    时间复杂度O(n2)

    #include<cstdio>
    int a,b,n,v[1024][1024];
    int mx1[1024][1024],mn1[1024][1024];
    int mx2[1024][1024],mn2[1024][1024];
    struct{
        int q[4096],qt[4096];
        int qs,qe;
        void clear(){
            qs=qe=0;
        }
        void push(int x,int t){
            while(qs<qe&&q[qe-1]<=x)--qe;
            qt[qe]=t;
            q[qe++]=x;
        }
        void chk(int p){
            while(qs<qe&&qt[qs]<=p)qs++;
        }
        int max(){
            return q[qs];
        }
    }q1;
    struct{
        int q[4096],qt[4096];
        int qs,qe;
        void clear(){
            qs=qe=0;
        }
        void push(int x,int t){
            while(qs<qe&&q[qe-1]>=x)--qe;
            qt[qe]=t;
            q[qe++]=x;
        }
        void chk(int p){
            while(qs<qe&&qt[qs]<=p)qs++;
        }
        int min(){
            return q[qs];
        }
    }q2;
    int main(){
        scanf("%d%d%d",&a,&b,&n);
        for(int i=0;i<a;i++)
        for(int j=0;j<b;j++)scanf("%d",v[i]+j);
        for(int i=0;i<a;i++){
            q1.clear();
            q2.clear();
            for(int j=0;j<n;j++)q1.push(v[i][j],j),q2.push(v[i][j],j);
            mx1[i][n-1]=q1.max();
            mn1[i][n-1]=q2.min();
            for(int j=n;j<b;j++){
                q1.push(v[i][j],j);
                q1.chk(j-n);
                mx1[i][j]=q1.max();
                q2.push(v[i][j],j);
                q2.chk(j-n);
                mn1[i][j]=q2.min();
            }
        }
        for(int j=0;j<b;j++){
            q1.clear();
            q2.clear();
            for(int i=0;i<n;i++)q1.push(mx1[i][j],i),q2.push(mn1[i][j],i);
            mx2[n-1][j]=q1.max();
            mn2[n-1][j]=q2.min();
            for(int i=n;i<a;i++){
                q1.push(mx1[i][j],i);
                q1.chk(i-n);
                mx2[i][j]=q1.max();
                q2.push(mn1[i][j],i);
                q2.chk(i-n);
                mn2[i][j]=q2.min();
            }
        }
        int minv=2147483647;
        for(int i=n-1;i<a;i++){
            for(int j=n-1;j<b;j++){
                if(mx2[i][j]-mn2[i][j]<minv)minv=mx2[i][j]-mn2[i][j];
            }
        }
        printf("%d",minv);
        return 0;
    }
  • 相关阅读:
    MySQL创建数据库简单命令
    工作的本质是解决问题
    使用消息中间件时,如何保证消息仅仅被消费一次?
    缓存穿透了怎么办?
    MySQL 数据库的提速器-写缓存(Change Buffer)
    删库了,我们一定要跑路吗?
    做好一件事的三要素
    一分钟简单了解 JSON Web Token
    聊一聊 MySQL 中的数据编辑过程中涉及的两阶段提交
    聊一聊 MySQL 数据库中的那些锁
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5136554.html
Copyright © 2020-2023  润新知