线段树练习题一
Description
桌子上零散地放着若干个盒子,桌子的后方是一堵墙。如右图所示。现在从桌子的前方射来一束平行光, 把盒子的影子投射到了墙上。问影子的总宽度是多少?
分析:给线段树每个节点增加一个域cover。cover=1表示该结点所对应的区间被完全覆盖,cover=0表示该结点所对应的区间未被完全覆盖,最后统计一下。
代码
const
maxn=1000000;
type
tnode=record
a,b:longint;
end;
var
tree:array[0..maxn] of tnode;
cover:array[0..maxn] of longint;
i,j,n,m,x,y:longint;
procedure create(p:longint);
var
m:longint;
begin
if tree[p].b-tree[p].a>1 then
begin
m:=(tree[p].a+tree[p].b) div 2;
tree[p*2].a:=tree[p].a;
tree[p*2].b:=m;
tree[p*2+1].a:=m;
tree[p*2+1].b:=tree[p].b;
create(p*2);
create(p*2+1);
end;
end;
procedure insert(p,x,y:longint);
var
m:longint;
begin
if cover[p]=0 then
begin
m:=(tree[p].a+tree[p].b) div 2;
if (tree[p].a=x) and (tree[p].b=y)
then cover[p]:=1
else if y<=m
then insert(p*2,x,y)
else if x>=m
then insert(p*2+1,x,y)
else begin
insert(p*2,x,m);
insert(p*2+1,m,y);
end;
end;
end;
function count(p:longint):longint;
var
m:longint;
begin
if cover[p]=1 then count:=tree[p].b-tree[p].a
else if tree[p].b-tree[p].a=1
then count:=0
else count:=count(p*2)+count(p*2+1);
end;
begin
readln(m);
tree[1].a:=1;
tree[1].b:=m;
create(1);
readln(n);
for i:=1 to n do
begin
readln(x,y);
insert(1,x,y);
end;
writeln(count(1));
end.