jzoj 1278. 排队 洛谷 P2880 [USACO07JAN]平衡的阵容Balanced Lineup

Description

  每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连续的牛来进行比赛.但是为了避免水平悬殊,牛的身高不应该相差太大.
  John 准备了Q (1 <= Q <= 180,000) 个可能的牛的选择和所有牛的身高 (1 <=身高 <= 1,000,000). 他想知道每一组里面最高和最低的牛的身高差别.

Input

  第一行: N 和 Q.
  第2..N+1行: 第i+1行是第i头牛的身高.
  第N+2..N+Q+1行: 两个整数, A 和 B (1 <= A <= B <= N), 表示从A到B的所有牛.

Output

  第1..Q行: 所有询问的回答 (最高和最低的牛的身高差), 每行一个.

Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2

Sample Output

6
3
0

分析:
这题就是求多次区间最大最小值,rmq模板题。其实线段树也能过。

代码(线段树):

type
 node=record
  max,min:longint;
 end;

var
 tree:array [1..100000*2] of node;
 h:array [1..100000] of longint;
 n,q,i,j,s,t,x,y:longint;

function max(x,y:longint):longint;
 begin
  if x>y then exit(x)
         else exit(y);
 end;

function min(x,y:longint):longint;
 begin
  if xthen exit(x)
         else exit(y);
 end;

procedure build(p,l,r:longint);
 var mid:longint;
begin
 if l=r then
  begin
   tree[p].max:=h[l];
   tree[p].min:=h[l];
   exit;
  end;
 mid:=(l+r) shr 1;
 build(p*2,l,mid);
 build(p*2+1,mid+1,r);
 tree[p].max:=max(tree[p*2].max,tree[p*2+1].max);
 tree[p].min:=min(tree[p*2].min,tree[p*2+1].min);
end;

procedure find(p,l,r,x,y:longint; var s,t:longint);
  var mid:longint;
      ss,tt:longint;
 begin
  if (l=x) and (r=y) then
   begin
    s:=tree[p].max; t:=tree[p].min;
    exit;
   end;
  mid:=(l+r) shr 1;
  if y<=mid then find(p*2,l,mid,x,y,s,t)
   else
    begin
     if x>mid then find(p*2+1,mid+1,r,x,y,s,t)
      else
       begin
        find(p*2,l,mid,x,mid,s,t);
        ss:=s; tt:=t;
        find(p*2+1,mid+1,r,mid+1,y,s,t);
        if sthen s:=ss;
        if t>tt then t:=tt;
        end;
    end;
 end;
begin
 readln(n,q);
 for i:=1 to n do
  read(h[i]);
 build(1,1,n);
 for i:=1 to q do
  begin
   read(x,y);
   find(1,1,n,x,y,s,t);
   writeln(s-t);
  end;
end.

代码(rmq):

Var n,q,i,j,x,y,k:longint;
    fmax,fmin:array[0..100005,0..20] of longint;
    a:array[0..100005] of longint;
function max(a,b:longint):longint;
begin
  if a>b then max:=a else max:=b;
end;
function min(a,b:longint):longint;
begin
  if a>b then min:=b else min:=a;
end;
begin
  readln(n,q);
  fillchar(fmin,sizeof(fmin),$7f);
  for I:=1 to n do
  begin
    readln(a[i]);
    fmin[i,0]:=a[i];
    fmax[i,0]:=a[i];
  end;
  for j:=1 to trunc(ln(n)/ln(2)) do
    for i:=1 to n-(1 shl j)+1 do
    begin
      fmax[i,j]:=max(fmax[i,j-1],fmax[i+1 shl (j-1),j-1]);
      fmin[i,j]:=min(fmin[i,j-1],fmin[i+1 shl (j-1),j-1]);
    end;
  for I:=1 to q do
  begin
    readln(x,y);
    k:=trunc(ln(y-x+1)/ln(2));
    writeln(max(fmax[x,k],fmax[y-(1 shl k)+1,k])-min(fmin[x,k],fmin[y-(1 shl k)+1,k]));
  end;
end.

你可能感兴趣的:(树)