bzoj1047[HAOI2007]理想的正方形
题意:
有一个a*b的整数组成的矩阵,求一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。a,b≤1000,n≤100
题解:
做4次单调队列。先利用单调队列求出第i行第j列到第i行第j+n-1列的最大最小值,再利用这个求出第i行第j列到第i+n-1行第j+n-1列的最大最小值。最后枚举一下求最小的差就行了。反思:本蒟蒻单调队列开始各种符号写反,比如判断是否要l++的那个条件。以及因为INF设得太小WA了一发,拍都拍不出,最后改成2147483647乱交一发结果过了。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 1500 5 #define inc(i,j,k) for(int i=j;i<=k;i++) 6 #define INF 2147483647 7 using namespace std; 8 9 int maxh[maxn][maxn],minh[maxn][maxn],maxl[maxn][maxn],minl[maxn][maxn]; 10 int v[maxn][maxn],q1[maxn],q2[maxn],a,b,n,l,r,ans; 11 int main(){ 12 scanf("%d%d%d",&a,&b,&n); inc(i,1,a)inc(j,1,b)scanf("%d",&v[i][j]); 13 inc(i,1,a){ 14 l=1; r=0; 15 inc(j,1,n){while(r>=l&&v[i][j]>q1[r])r--; q1[++r]=v[i][j]; q2[r]=j;} maxh[i][1]=q1[l]; 16 inc(j,n+1,b){ 17 if(j-n>=q2[l])l++; while(r>=l&&v[i][j]>q1[r])r--; 18 q1[++r]=v[i][j]; q2[r]=j; maxh[i][j-n+1]=q1[l]; 19 } 20 } 21 inc(i,1,a){ 22 l=1; r=0; 23 inc(j,1,n){while(r>=l&&v[i][j]<q1[r])r--; q1[++r]=v[i][j]; q2[r]=j;} minh[i][1]=q1[l]; 24 inc(j,n+1,b){ 25 if(j-n>=q2[l])l++; while(r>=l&&v[i][j]<q1[r])r--; 26 q1[++r]=v[i][j]; q2[r]=j; minh[i][j-n+1]=q1[l]; 27 } 28 } 29 inc(j,1,b){ 30 l=1; r=0; 31 inc(i,1,n){while(r>=l&&maxh[i][j]>q1[r])r--; q1[++r]=maxh[i][j]; q2[r]=i;} maxl[1][j]=q1[l]; 32 inc(i,n+1,a){ 33 if(i-n>=q2[l])l++; while(r>=l&&maxh[i][j]>q1[r])r--; 34 q1[++r]=maxh[i][j]; q2[r]=i; maxl[i-n+1][j]=q1[l]; 35 } 36 } 37 inc(j,1,b){ 38 l=1; r=0; 39 inc(i,1,n){while(r>=l&&minh[i][j]<q1[r])r--; q1[++r]=minh[i][j]; q2[r]=i;} minl[1][j]=q1[l]; 40 inc(i,n+1,a){ 41 if(i-n>=q2[l])l++; while(r>=l&&minh[i][j]<q1[r])r--; 42 q1[++r]=minh[i][j]; q2[r]=i; minl[i-n+1][j]=q1[l]; 43 } 44 } 45 ans=INF; 46 inc(i,1,a-n+1)inc(j,1,b-n+1){ 47 ans=min(ans,maxl[i][j]-minl[i][j]); 48 } 49 printf("%d",ans); return 0; 50 }
20160527