ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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;
}

 

posted on 2016-01-16 23:00  nul  阅读(181)  评论(0编辑  收藏  举报