Description
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
Input
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
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
HINT
问题规模
(1)矩阵中的所有数都不超过1,000,000,000
(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10
(3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
(1)矩阵中的所有数都不超过1,000,000,000
(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10
(3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
题解
网上的题解有用单调队列做的,私认为这道题暴力完全可以水过去...
这里给出一种$RMQ$的做法。
二维的$RMQ$求正方形内的最值,和一维没什么不同,只是倍增以及询问的时候要分四块。
1 #include<cmath> 2 #include<ctime> 3 #include<stack> 4 #include<queue> 5 #include<string> 6 #include<cstdio> 7 #include<cstring> 8 #include<cstdlib> 9 #include<iostream> 10 #include<algorithm> 11 using namespace std; 12 const int N=1000; 13 14 int a,b,n,op; 15 int minn[N+5][N+5][15],maxn[N+5][N+5][15]; 16 17 int main() 18 { 19 scanf("%d%d%d",&a,&b,&n); 20 for (int i=1;i<=a;i++) 21 for (int j=1;j<=b;j++) 22 { 23 scanf("%d",&minn[i][j][0]); 24 maxn[i][j][0]=minn[i][j][0]; 25 } 26 op=log2(n); 27 for (int t=1;t<=op;t++) 28 for (int i=1;i+(1<<t)-1<=a;i++) 29 for (int j=1;j+(1<<t)-1<=b;j++) 30 { 31 minn[i][j][t]=min(minn[i][j][t-1],minn[i][j+(1<<t-1)][t-1]); 32 minn[i][j][t]=min(minn[i][j][t],minn[i+(1<<t-1)][j][t-1]); 33 minn[i][j][t]=min(minn[i][j][t],minn[i+(1<<t-1)][j+(1<<t-1)][t-1]); 34 maxn[i][j][t]=max(maxn[i][j][t-1],maxn[i][j+(1<<t-1)][t-1]); 35 maxn[i][j][t]=max(maxn[i][j][t],maxn[i+(1<<t-1)][j][t-1]); 36 maxn[i][j][t]=max(maxn[i][j][t],maxn[i+(1<<t-1)][j+(1<<t-1)][t-1]); 37 } 38 int ansmax,ansmin,ans=2e9; 39 for (int i=1;i+n-1<=a;i++) 40 for (int j=1;j+n-1<=b;j++) 41 { 42 ansmax=max(maxn[i][j][op],maxn[i][j+n-(1<<op)][op]); 43 ansmax=max(ansmax,maxn[i+n-(1<<op)][j][op]); 44 ansmax=max(ansmax,maxn[i+n-(1<<op)][j+n-(1<<op)][op]); 45 ansmin=min(minn[i][j][op],minn[i][j+n-(1<<op)][op]); 46 ansmin=min(ansmin,minn[i+n-(1<<op)][j][op]); 47 ansmin=min(ansmin,minn[i+n-(1<<op)][j+n-(1<<op)][op]); 48 ans=min(ans,ansmax-ansmin); 49 } 50 printf("%d ",ans); 51 return 0; 52 }