• 洛谷 U4792 Acheing


     U4792 Acheing

    题目描述

    给你一个n*m的矩阵,请你求出其中边长为k的子矩形,使得这个矩形中最大值减最小值最小。

    输入输出格式

    输入格式:

     

    n,m,k 接下来一个n*m的子矩阵.

     

    输出格式:

     

    一个数,即最小值.

     

    输入输出样例

    输入样例#1:
    5 4 2
    1 2 5 6
    0 17 16 0
    16 17 2 1
    2 10 2 1
    1 2 2 2
    输出样例#1:
    1

    说明

    1<=n,m<=1000

    1<=k<=min(n,m)

    /*
    二维的单调队列
    先单调队列处理好每一列中一段连续k个的最大最小值
    然后做一维的单调队列
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 1010
    using namespace std;
    int n,m,w,ans=0x7fffffff;
    int a[maxn][maxn];
    int qmax[maxn],qmin[maxn],tmax,tmin,wmax,wmin;
    int maxx[maxn][maxn],minn[maxn][maxn]; 
    int init()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int main()
    {
        n=init();m=init();w=init();
        for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
            a[i][j]=init();
        for(int j=1;j<=m;j++)
        {
            tmax=tmin=1;
            wmax=wmin=0;
            for(int i=1;i<=n;i++)
            {
                if(i-qmax[tmax]+1>w)tmax++;
                while(wmax>=tmax&&a[i][j]>=a[qmax[wmax]][j])wmax--;
                wmax++;qmax[wmax]=i;
                
                if(i-qmin[tmin]+1>w)tmin++;
                while(wmin>=tmin&&a[i][j]<=a[qmin[wmin]][j])wmin--;
                wmin++;qmin[wmin]=i;
                
                if(i>=w)maxx[i][j]=a[qmax[tmax]][j],minn[i][j]=a[qmin[tmin]][j];
            }
        }
        for(int i=w;i<=n;i++)
        {
            tmax=tmin=1;
            wmax=wmin=0;
            for(int j=1;j<=m;j++)
            {
                if(j-qmax[tmax]+1>w)tmax++;
                while(wmax>=tmax&&maxx[i][j]>=maxx[i][qmax[wmax]])wmax--;
                wmax++;qmax[wmax]=j;
                
                if(j-qmin[tmin]+1>w)tmin++;
                while(wmin>=tmin&&minn[i][j]<=minn[i][qmin[wmin]])wmin--;
                wmin++;qmin[wmin]=j;
                
                if(j>=w)ans=min(ans,maxx[i][qmax[tmax]]-minn[i][qmin[tmin]]);
            }
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    【Red Hat Linux基础】 磁盘分区详细教程
    分区间统计sql、删除重复数据
    sql 建立索引之前计算区分度
    jvm调优
    最短路径-迷宫类
    comparable and comparator 比较
    刷题之Implement strStr()、Climbing Stairs
    对线程池简单理解
    hash表系列(转)
    对于AVL树和红黑树的理解
  • 原文地址:https://www.cnblogs.com/dingmenghao/p/6044603.html
Copyright © 2020-2023  润新知