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.
结果写完就被鄙视了,z55250825 ORZ,其实可以用单调队列
1 const 2 maxn=1010; 3 var 4 a,b:array[0..maxn,0..maxn]of longint; 5 n,m,k,ans:longint; 6 7 function min(x,y:longint):longint; 8 begin 9 if x<y then exit(x); 10 exit(y); 11 end; 12 13 procedure init; 14 var 15 i,j:longint; 16 begin 17 read(n,m,k); 18 for i:=1 to n do 19 for j:=1 to m do 20 begin 21 read(a[i,j]); 22 b[i,j]:=a[i,j]; 23 end; 24 end; 25 26 var 27 q:array[0..maxn,0..1]of longint; 28 head,tail:longint; 29 30 procedure work; 31 var 32 i,j:longint; 33 begin 34 for i:=1 to n do 35 begin 36 head:=1; 37 tail:=0; 38 for j:=1 to m do 39 begin 40 while (tail>=head) and (q[tail,1]<=a[i,j]) do 41 dec(tail); 42 inc(tail); 43 q[tail,0]:=j; 44 q[tail,1]:=a[i,j]; 45 while q[head,0]<=j-k do 46 inc(head); 47 a[i,j]:=q[head,1]; 48 end; 49 end; 50 for j:=1 to m do 51 begin 52 head:=1; 53 tail:=0; 54 for i:=1 to n do 55 begin 56 while (tail>=head) and (q[tail,1]<=a[i,j]) do 57 dec(tail); 58 inc(tail); 59 q[tail,0]:=i; 60 q[tail,1]:=a[i,j]; 61 while q[head,0]<=i-k do 62 inc(head); 63 a[i,j]:=q[head,1]; 64 end; 65 end; 66 for i:=1 to n do 67 begin 68 head:=1; 69 tail:=0; 70 for j:=1 to m do 71 begin 72 while (tail>=head) and (q[tail,1]>=b[i,j]) do 73 dec(tail); 74 inc(tail); 75 q[tail,0]:=j; 76 q[tail,1]:=b[i,j]; 77 while q[head,0]<=j-k do 78 inc(head); 79 b[i,j]:=q[head,1]; 80 end; 81 end; 82 for j:=1 to m do 83 begin 84 head:=1; 85 tail:=0; 86 for i:=1 to n do 87 begin 88 while (tail>=head) and (q[tail,1]>=b[i,j]) do 89 dec(tail); 90 inc(tail); 91 q[tail,0]:=i; 92 q[tail,1]:=b[i,j]; 93 while q[head,0]<=i-k do 94 inc(head); 95 b[i,j]:=q[head,1]; 96 end; 97 end; 98 ans:=maxlongint; 99 for i:=k to n do 100 for j:=k to m do 101 ans:=min(ans,a[i,j]-b[i,j]); 102 write(ans); 103 end; 104 105 begin 106 init; 107 work; 108 end.
Wikioi上实在是过不了,然后写了一个C++的
1 #include<cstdio> 2 using namespace std; 3 4 const int maxn=1510; 5 6 int a[maxn][maxn],b[maxn][maxn],n,m,k,ans; 7 8 int min(int x,int y) 9 { 10 return(x<y?x:y); 11 } 12 13 void init() 14 { 15 int i,j; 16 scanf("%d%d%d",&n,&m,&k); 17 for(i=1;i<=n;i++) 18 for(j=1;j<=m;j++) 19 scanf("%d",&a[i][j]),b[i][j]=a[i][j]; 20 } 21 22 int q[maxn][2],head,tail; 23 24 void work() 25 { 26 int i,j; 27 for(i=1;i<=n;i++) 28 { 29 head=1;tail=0; 30 for(j=1;j<=m;j++) 31 { 32 while(tail>=head & q[tail][1]<=a[i][j])--tail; 33 tail++; 34 q[tail][0]=j; 35 q[tail][1]=a[i][j]; 36 while(q[head][0]<=j-k)head++; 37 a[i][j]=q[head][1]; 38 } 39 } 40 for(j=1;j<=m;j++) 41 { 42 head=1;tail=0; 43 for(i=1;i<=n;i++) 44 { 45 while(tail>=head & q[tail][1]<=a[i][j])tail--; 46 tail++; 47 q[tail][0]=i; 48 q[tail][1]=a[i][j]; 49 while(q[head][0]<=i-k)head++; 50 a[i][j]=q[head][1]; 51 } 52 } 53 for(i=1;i<=n;i++) 54 { 55 head=1;tail=0; 56 for(j=1;j<=m;j++) 57 { 58 while(tail>=head & q[tail][1]>=b[i][j])tail--; 59 tail++; 60 q[tail][0]=j; 61 q[tail][1]=b[i][j]; 62 while(q[head][0]<=j-k)head++; 63 b[i][j]=q[head][1]; 64 } 65 } 66 for(j=1;j<=m;j++) 67 { 68 head=1;tail=0; 69 for(i=1;i<=n;i++) 70 { 71 while(tail>=head & q[tail][1]>=b[i][j])tail--; 72 tail++; 73 q[tail][0]=i; 74 q[tail][1]=b[i][j]; 75 while(q[head][0]<=i-k)head++; 76 b[i][j]=q[head][1]; 77 } 78 } 79 ans=2000000000; 80 for(i=k;i<=n;i++) 81 for(j=k;j<=m;j++) 82 ans=min(ans,a[i][j]-b[i][j]); 83 printf("%d",ans); 84 } 85 86 int main() 87 { 88 init(); 89 work(); 90 return 0; 91 }