1047: [HAOI2007]理想的正方形 - BZOJ

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.
View Code

 结果写完就被鄙视了,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.
View Code

 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 }
View Code

 

posted @ 2014-04-07 18:03  Randolph87  阅读(233)  评论(0编辑  收藏  举报