標籤:des style class blog code http
1047: [HAOI2007]理想的正方形Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1402 Solved: 738
[Submit][Status]Description
有一個a*b的整數組成的矩陣,現請你從中找出一個n*n的正方形地區,使得該地區所有數中的最大值和最小值的差最小。
Input
第一行為3個整數,分別表示a,b,n的值第二行至第a+1行每行為b個非負整數,表示矩陣中相應位置上的數。每行相鄰兩數之間用一空格分隔。
Output
僅一個整數,為a*b矩陣中所有“n*n正方形地區中的最大整數和最小整數的差值”的最小值。
Sample Input5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
Sample Output1
問題規模
(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
HINT
題解:
真是一道好題!
我一開始只想到了二維的RMQ,分析了一下時間和空間複雜度,感覺都承受不起……
一看題解,恍然大悟,因為該問題的特殊性,固定了以n為邊長,所以只要用單調隊列即可,RMQ多餘了,用不到RMQ的優點
(而且,我參看的大牛的代碼很巧妙的使代碼量降了下來,如下這是一種技巧,以後要掌握)
代碼:
1 uses math; 2 var f:array[1..2,0..1100,0..1100] of longint; 3 g,c:array[0..1100,0..1100] of longint; 4 i,j,a,b,n,ans:longint; 5 procedure init; 6 begin 7 readln(a,b,n); 8 for i:=1 to a do 9 begin10 for j:=1 to b do read(c[i,j]);11 readln;12 end;13 end;14 procedure work(x:longint);15 var i,j,l,r:longint;16 q:array[0..1500] of longint;17 begin18 for i:=1 to a do19 begin20 fillchar(q,sizeof(q),0);21 l:=1;r:=0;22 for j:=1 to b do23 begin24 while (l<=r) and (c[i,q[r]]<=c[i,j]) do dec(r);25 inc(r);q[r]:=j;26 while (l<r) and (q[l]<j-n+1) do inc(l);27 g[i,j]:=c[i,q[l]];28 end;29 end;30 for i:=1 to b do31 begin32 fillchar(q,sizeof(q),0);33 l:=1;r:=0;34 for j:=1 to a do35 begin36 while (l<=r) and (g[q[r],i]<=g[j,i]) do dec(r);37 inc(r);q[r]:=j;38 while (l<r) and (q[l]<j-n+1) do inc(l);39 f[x,j,i]:=g[q[l],i];40 end;41 end;42 end;43 procedure main;44 begin45 work(1);46 for i:=1 to a do47 for j:=1 to b do48 c[i,j]:=0-c[i,j];49 work(2);50 ans:=maxlongint;51 for i:=n to a do52 for j:=n to b do53 ans:=min(ans,f[1,i,j]+f[2,i,j]);54 writeln(ans);55 end;56 begin57 init;58 main;59 end.
View Code