登山

问题描述:

有一座延绵不断、跌宕起伏的山,最低处海拔为0米,最高处海拔不超过8848米。从这座山的一端走到另一端的过程中,每走 1 米海拔高度就升高 1 米或者降低 1 米。有 Q 个登山队计划在这座山的不同区段登山,当他们攀到各自区段内的最高峰时,就会插上他们的队旗。请你写一个程序找出他们插旗的高度。

输入说明:

从CLIMB.IN 输入数据。第一行为 N(N≤106 ),表示山两端的跨度。接下来 N+1 行,每行一个非负整数Hi (i=0..N),表示该位置的海拔高度(单位:米),其中 H0=Hn=0。然后是一个正整数Q(Q≤7000),表示登山队的数量。紧跟的Q行,每行两个数Ai和Bi,表示第 i 个登山队攀爬的区段[Ai,Bi],其中0≤Ai≤Bi≤N。

初识ST算法

输出说明:

答案输出到CLIMB.OUT,共Q行,每行一个整数,表示第 i 个登山队攀爬区段中最高点的高度。

样例输入:

10

0

1

2

3

2

3

4

3

2

1

0

5

0 10

2 4

3 7

7 9

8 8

样例输出:

4

3

4

3

2

 

分析:

就是一个比较显然的RMQ问题,

正好刚学的ST算法,来试验一番。

这道题不是完全考算法,

个人认为,有两点注意事项:

1.这个坐标是从0出发的,不要因为做题的惯性不考虑0

2.这个题的数据范围也是较大的,100万,

要是数组开的比较随意就完了。。。

应当用计算器算一下,

开100W*20的数组刚好够用,

(开始随意的就10W*200(惯性),结果最后俩点201了,

然后100W*200,爆内存。。。。)

内存用了82M。。。。。

program climb;
  var
    i,j,n,m,k,l,q,a,b:longint;
    d:array[0..1000000,0..20]of longint;
  function max(x,y:longint):Longint;
    begin
      if x>y then exit(x);
      exit(y);
    end;
  begin
    assign(input,'climb.in');
    reset(input);
    assign(output,'climb.out');
    rewrite(output);
    readln(n);
    for i:=0 to n do readln(d[i,0]);
    for j:=1 to trunc(ln(n)/ln(2)) do
      for i:=0 to n-1<<j+1 do
        d[i,j]:=max(d[i,j-1],d[i+1<<(j-1),j-1]);
    readln(q);
    for i:=1 to q do
      begin
        readln(a,b);
        k:=trunc(ln(b-a+1)/ln(2));
        m:=max(d[a,k],d[b-1<<k+1,k]);
        writeln(m);
      end;
    close(input);
    close(output);
  end.

分类:

技术点:

相关文章: