题目描述
给你一个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; }