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

 

你可能感兴趣的:(2007)