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
Sample Output
1
问题规模
(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果然什么都忘了
就是先做一遍右边的,把右边n格的最大值最小值存到最左边这一格
然后做一遍向下的,把下面n格的最值存到这一格,现在,每一个n*n的正方形的信息都存到左上角了,扫一遍就行了
1 const 2 maxn=1010; 3 var 4 a,b:array[0..maxn,0..maxn]of longint; 5 n,m,k:longint; 6 7 procedure down(var x:longint;y:longint); 8 begin 9 if x>y then x:=y; 10 end; 11 12 procedure up(var x,y:longint); 13 begin 14 if x<y then x:=y; 15 end; 16 17 procedure main; 18 var 19 i,j,l,s,ans:longint; 20 begin 21 read(n,m,k); 22 for i:=1 to n do 23 for j:=1 to m do 24 begin 25 read(a[i,j]); 26 b[i,j]:=a[i,j]; 27 end; 28 l:=1; 29 while l<k do 30 begin 31 for i:=1 to n do 32 for j:=1 to m do 33 begin 34 s:=j+l; 35 down(s,m-l+1); 36 down(s,j+k-l); 37 up(a[i,j],a[i,s]); 38 down(b[i,j],b[i,s]); 39 end; 40 l:=l<<1; 41 end; 42 l:=1; 43 while l<k do 44 begin 45 for i:=1 to n do 46 for j:=1 to m do 47 begin 48 s:=i+l; 49 down(s,n-l+1); 50 down(s,i+k-l); 51 up(a[i,j],a[s,j]); 52 down(b[i,j],b[s,j]); 53 end; 54 l:=l<<1; 55 end; 56 ans:=maxlongint; 57 for i:=1 to n-k+1 do 58 for j:=1 to m-k+1 do 59 down(ans,a[i,j]-b[i,j]); 60 write(ans); 61 end; 62 63 begin 64 main; 65 end.