洛谷 U4792 Acheing 单调队列

U4792 Acheing

    • 5通过
    • 43提交
  • 题目提供者Acheing
  • 标签
  • 难度尚无评定

  

最新讨论

  • 暂时没有讨论

题目背景

题目并没有什么含义,只是想宣传一下自己的博客,Acheing.com

题目描述

给你一个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)

//单调队列运用 解决二维线段树超时的问题
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
    register int x=0;bool f=1;
    register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return f?x:-x;
}
const int N=1010;
int n,m,w,ans=0x7fffffff;
int a[N][N];
int qmax[N],qmin[N],tmax,tmin,wmax,wmin;
int maxx[N][N],minn[N][N]; 
int main(){
    n=read();m=read();w=read();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            a[i][j]=read();
        }
    }
    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++;
            for(;tmax<=wmax&&a[i][j]>=a[qmax[wmax]][j];wmax--);
            qmax[++wmax]=i;
            if(i-qmin[tmin]+1>w) tmin++;
            for(;tmin<=wmin&&a[i][j]<=a[qmin[wmin]][j];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++;
            for(;tmax<=wmax&&maxx[i][j]>=maxx[i][qmax[wmax]];wmax--);
            qmax[++wmax]=j;
            if(j-qmin[tmin]+1>w) tmin++;
            for(;tmin<=wmin&&minn[i][j]<=minn[i][qmin[wmin]];wmin--);
            qmin[++wmin]=j;
            if(j>=w) ans=min(ans,maxx[i][qmax[tmax]]-minn[i][qmin[tmin]]);
        }
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2016-11-10 16:55  神犇(shenben)  阅读(305)  评论(0编辑  收藏  举报