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

 

posted @ 2016-11-08 20:56  岂是蓬蒿人  阅读(156)  评论(0编辑  收藏  举报