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