HAOI2007 理想的正方形

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 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

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    begin
10     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  begin
18  for i:=1 to a do
19   begin
20    fillchar(q,sizeof(q),0);
21    l:=1;r:=0;
22    for j:=1 to b do
23     begin
24     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 do
31   begin
32    fillchar(q,sizeof(q),0);
33    l:=1;r:=0;
34    for j:=1 to a do
35     begin
36     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  begin
45  work(1);
46  for i:=1 to a do
47   for j:=1 to b do
48    c[i,j]:=0-c[i,j];
49  work(2);
50  ans:=maxlongint;
51  for i:=n to a do
52   for j:=n to b do
53    ans:=min(ans,f[1,i,j]+f[2,i,j]);
54  writeln(ans);
55  end;
56 begin
57  init;
58  main;
59 end.
View Code

 

posted @ 2014-06-26 13:08  ZYF-ZYF  Views(185)  Comments(0Edit  收藏  举报