• P2216 [HAOI2007]理想的正方形 单调队列


      

    题目描述

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

    输入格式

    第一行为3个整数,分别表示a,b,n的值

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

    输出格式

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

    输入输出样例

    输入 #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)矩阵中的所有数都不超过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

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    const int N=1000+10;
    int mp[N][N],maxx[N][N],minn[N][N],n,m,k;
    int de[N],de2[N];
    
    int main()
    {
        cin>>n>>m>>k;
        rep(i,1,n)rep(j,1,m)scanf("%d",&mp[i][j]),maxx[i][j]=0,minn[i][j]=0;
    
        rep(i,1,n)
        {
            int l=1,r=0,l2=1,r2=0;
            rep(j,1,k)
            {
                while(l<=r&&mp[i][de[r]]>=mp[i][j])r--;
                de[++r]=j;
                while(l2<=r2&&mp[i][de2[r2]]<=mp[i][j])r2--;
                de2[++r2]=j;
            }
            minn[i][1]=mp[i][de[l]];
            maxx[i][1]=mp[i][de2[l]];
    
            rep(j,2,m-k+1)
            {
                while(l<=r&&mp[i][de[r]]>=mp[i][j+k-1])r--;
                while(l2<=r2&&mp[i][de2[r2]]<=mp[i][j+k-1])r2--;
                de[++r]=j+k-1;
                de2[++r2]=j+k-1;
                if(l<=r&&de[l]<j)l++;
                if(l2<=r2&&de2[l2]<j)l2++;
                minn[i][j]=mp[i][de[l]];
                maxx[i][j]=mp[i][de2[l2]];
            }
        }
        rep(j,1,m)
        {
            int l=1,r=0,l2=1,r2=0;
            rep(i,1,k)
            {
                while(l<=r&&minn[de[r]][j]>=minn[i][j])r--;
                de[++r]=i;
                while(l2<=r2&&maxx[de2[r2]][j]<=maxx[i][j])r2--;
                de2[++r2]=i;
            }
            minn[1][j]=minn[de[l]][j];
            maxx[1][j]=maxx[de2[l2]][j];
    
            rep(i,2,n-k+1)
            {
                while(l<=r&&minn[de[r]][j]>=minn[i+k-1][j])r--;
                while(l2<=r2&&maxx[de2[r2]][j]<=maxx[i+k-1][j])r2--;
                de[++r]=i+k-1;
                de2[++r2]=i+k-1;
                if(l<=r&&de[l]<i)l++;
                if(l2<=r2&&de2[l2]<i)l2++;
                minn[i][j]=minn[de[l]][j];
                maxx[i][j]=maxx[de2[l2]][j];
            }
        }
        int ans=inf;
        rep(i,1,n-k+1)
        rep(j,1,m-k+1)
        ans=min(ans,maxx[i][j]-minn[i][j]);
        cout<<ans;
    
        return 0;
    }
    View Code
  • 相关阅读:
    python爬虫之Scrapy框架
    Web自动化测试工具:Selenium
    多线程爬取新闻标题和链接
    python里更推荐使用的requests库
    python豆瓣的简单爬虫
    4 个好用的 Linux 监控工具
    8个你会爱上的 VS Code 扩展
    SpringBoot 构建 Docker 镜像的 3 种方式
    OAuth2 图解
    Prometheus + Grafana 监控 SpringBoot
  • 原文地址:https://www.cnblogs.com/bxd123/p/11393926.html
Copyright © 2020-2023  润新知