poj 2528 Mayor's posters 线段树

题意:n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)。求出最后还能看见多少张海报。

分析:一看就知道是线段树啦。然后就先离散化一下,再就是个普通的线段树啦。注意在插入操作时要把原来的海报覆盖掉就好啦。(啦够了没有)

代码:

var
  o,e,i,j,ans,x,y,n:longint;
  l,r:array[1..10000] of longint;
  a:array[0..20000,1..2] of longint;
  v:array[1..10000] of boolean;
  t:array[1..400000,1..3] of longint;

procedure qsort(l,r:longint);
var
  i,j,k:longint;
begin
  if l>=r then exit;
  i:=l;
  j:=r;
  k:=a[(i+j) div 2,1];
  repeat
    while a[i,1]<k do inc(i);
    while a[j,1]>k do dec(j);
    if i<=j then
    begin
      a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
      inc(i);dec(j);
    end;
  until i>j;
  qsort(i,r);
  qsort(l,j);
end;

procedure hehe(d,l,r:longint);
var
  m:longint;
begin
  t[d,1]:=l;
  t[d,2]:=r;
  t[d,3]:=0;
  if l=r then exit;
  m:=(l+r) div 2;
  hehe(d*2,l,m);
  hehe(d*2+1,m+1,r);
end;

procedure insert(d,l,r,z:longint);
var
  m:longint;
begin
  if (t[d,1]=l)and(t[d,2]=r) then
  begin
    t[d,3]:=z;
    exit;
  end;
  if t[d,3]>0 then
  begin
    t[d*2,3]:=t[d,3];
    t[d*2+1,3]:=t[d,3];
    t[d,3]:=0;
  end;
  m:=(t[d,1]+t[d,2]) div 2;
  if r<=m
    then insert(d*2,l,r,z)
    else if l>m
           then insert(d*2+1,l,r,z)
           else begin
                  insert(d*2,l,m,z);
                  insert(d*2+1,m+1,r,z);
                end;
end;

procedure count(d:longint);
begin
  if t[d,3]>0 then
  begin
    v[t[d,3]]:=false;
    exit;
  end;
  if t[d,1]=t[d,2] then exit;
  count(d*2);
  count(d*2+1);
end;

begin
  readln(o);
  for e:=1 to o do
  begin
    readln(n);
    for i:=1 to n do
    begin
      readln(x,y);
      a[i*2-1,1]:=x;
      a[i*2-1,2]:=i;
      a[i*2,1]:=y;
      a[i*2,2]:=i;
    end;
    qsort(1,n*2);
    j:=0;
    a[0,1]:=0;
    fillchar(l,sizeof(l),0);
    fillchar(r,sizeof(r),0);
    for i:=1 to n*2 do
    begin
      if a[i,1]<>a[i-1,1] then inc(j);
      if l[a[i,2]]=0
       then l[a[i,2]]:=j
       else r[a[i,2]]:=j;
    end;
    hehe(1,1,j);
    for i:=1 to n do
      insert(1,l[i],r[i],i);
    fillchar(v,sizeof(v),true);
    count(1);
    ans:=0;
    for i:=1 to n do
      if v[i]=false then inc(ans);
    writeln(ans);
  end;
end.


你可能感兴趣的:(poj 2528 Mayor's posters 线段树)