BZOJ1047: [HAOI2007]理想的正方形
1047: [HAOI2007]理想的正方形
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3448 Solved: 1894
[Submit][Status][Discuss]
Description
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。
Input
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000
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
思路{直接二维ST表就可以了,SB的我之前以为4个ST表,打完发现一个就可以了.}
#include<bits/stdc++.h> #define RG register #define il inline #define LEN (1<<(k-1)) #define Inf (1<<30) #define N 1001 using namespace std; int rd[10][N][N][2]; int b[N][N],n,m,len,lim; int max(int a,int b,int c,int d){a=max(a,b);c=max(c,d),a=max(a,c);return a;} int min(int a,int b,int c,int d){a=min(a,b),c=min(c,d),a=min(a,c);return a;} void Modify(int x,int y,int &X){ int Max=max(rd[lim][x][y][1],rd[lim][x+len-(1<<lim)][y][1], rd[lim][x][y+len-(1<<lim)][1],rd[lim][x+len-(1<<lim)][y+len-(1<<lim)][1]); int Min=min(rd[lim][x][y][0],rd[lim][x+len-(1<<lim)][y][0], rd[lim][x][y+len-(1<<lim)][0],rd[lim][x+len-(1<<lim)][y+len-(1<<lim)][0]); X=min(X,Max-Min); } int main(){ scanf("%d%d%d",&n,&m,&len); for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){ scanf("%d",&b[i][j]); rd[0][i][j][0]=rd[0][i][j][1]=b[i][j]; } for(lim=0;(1<<lim)<=len;++lim);lim--; for(int k=1;k<=lim;++k){ for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){ if(i+(1<<k)<=n+1&&j+(1<<k)<=m+1){ rd[k][i][j][1]=max(rd[k-1][i][j][1],rd[k-1][i+LEN][j][1],rd[k-1][i][j+LEN][1],rd[k-1][i+LEN][j+LEN][1]); rd[k][i][j][0]=min(rd[k-1][i][j][0],rd[k-1][i+LEN][j][0],rd[k-1][i][j+LEN][0],rd[k-1][i+LEN][j+LEN][0]); } } }int Ans=Inf;for(int i=1;i+len-1<=n;++i)for(int j=1;j+len-1<=m;++j)Modify(i,j,Ans); cout<<Ans; return 0; }