1047: [HAOI2007]理想的正方形
Description
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。
Input
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
Output
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
Sample Input
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
Sample Output
1
考虑一下这个题目。。。行与行之间是独立的。。。
所以我们可以先求出每一行,然后在拓展到每一行。。。
用f[i][j]表示第j行i-n+1 到 i 的最大值,g[i][j]表示最小值。。。
然后我们会发现如果枚举会炸。。。所以想到队列优化。。。这样就可以做啦....
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 1000+5 14 #define maxm 1000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 int a[maxn][maxm],f[maxn][maxm],g[maxn][maxm]; 30 struct num{ 31 int w,id; 32 }q[maxn]; 33 int main(){ 34 //freopen("input.txt","r",stdin); 35 //freopen("output.txt","w",stdout); 36 int t=read(),b=read(),n=read(); 37 for1(i,t) 38 for1(j,b) 39 a[i][j]=read(); 40 41 for1(i,t){ 42 int l=1,r=0; 43 for1(j,b){ 44 while(q[r].w<=a[i][j]&&l<=r&&r)r--; 45 while(q[l].id<j-n+1&&l<=r&&l)l++; 46 q[++r].id=j;q[r].w=a[i][j]; 47 f[i][j]=q[l].w; 48 } 49 } 50 for1(i,t){ 51 int l=1,r=0; 52 for1(j,b){ 53 while(q[r].w>=a[i][j]&&l<=r&&r)r--; 54 while(q[l].id<j-n+1&&l<=r&&l)l++; 55 q[++r].id=j;q[r].w=a[i][j]; 56 g[i][j]=q[l].w; 57 } 58 } 59 int ans=inf; 60 for(int i=1;i<=t-n+1;i++) 61 for(int j=n;j<=b;j++){ 62 int mi=inf,mx=0; 63 for0(k,n-1){ 64 mi=min(mi,g[i+k][j]); 65 mx=max(mx,f[i+k][j]); 66 } 67 ans=min(ans,mx-mi); 68 } 69 printf("%d",ans); 70 return 0; 71 }