bzoj1047[HAOI2007]理想的正方形

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

posted @ 2016-07-23 13:11  YuanZiming  阅读(282)  评论(0编辑  收藏  举报