您的位置:首页 > 其它

线段树 例一

2016-05-14 07:53 381 查看
题目大意

  桌子上零散地放着若干个盒子,桌子的后方是一堵墙。如右图所示。现在从桌子的前射来一束平行光, 把盒子的影子投射到了墙上。问影子的总宽度是多少?

 

分析

  1.就是x轴上有若干条线段,求线段覆盖的总长度。

  2.给线段树每个节点增加一个域cover。cover=1表示该结点所对应的区间被完全覆盖,cover=0表示该结点所对应的区间未被完全覆盖。最后统计被完全覆盖的节点的长度。

  3.线段树可以用数组静态储存:F[r]的左右儿子分别为f[r*2] f[r*2+1]。但是这样写的代码虽然比较简单,但是会浪费很多的空间,因为不是每一个节点会被放置。

type
tnode=record
l,r:longint;
c:longint;
end;

var
t:array[1..1000000] of tnode;
i,j,k:longint;
x,y:longint;
n,m:longint;

procedure insert(root,x,y:longint);
var
i,j,k:longint;
mid:longint;

begin
with t[root] do
begin
if c=0 then
begin
mid:=(l+r) div 2;
if (l=x) and (r=y)
then
begin
c:=1;
exit;
end;
if (l<=x) and (mid>=y)
then
begin
insert(root*2,x,y);
exit;
end;
if (mid<=x) and (r>=y)
then
begin
insert(root*2+1,x,y);
exit;
end;
insert(root*2,x,mid);
insert(root*2+1,mid,y);
end;
end;
end;

function find(root:longint):longint;
var
mid:longint;
begin
with t[root] do
begin
if c=1 then exit(r-l);
if r-l=1
then exit(0)
else exit(find(root*2)+find(root*2+1));
end;
end;

procedure make(root:longint);
var
mid:longint;
begin
with t[root] do
begin
if r-l>1 then
begin
mid:=(l+r) div 2;
t[root*2].l:=l;
t[root*2].r:=mid;
t[root*2+1].l:=mid;
t[root*2+1].r:=r;
make(root*2);
make(root*2+1);
end;
end;
end;

begin
readln(m);
fillchar(t,sizeof(t),0);
t[1].l:=1; t[1].r:=m;
make(1);
readln(n);
for i:=1 to n do
begin
readln(x,y);
insert(1,x,y);
end;
write(find(1));
end.

  4.线段树还可以用链表动态储存:每当要递归到下一层的时候,如果这个子树还没有建立,就新建这个子树。这样理论上会省空间,但是代码比较复杂。

type
pnode=^tnode;
tnode=record
lc,rc:pnode;
c:longint;
end;

var
t:pnode;
i,j,k:longint;
x,y:longint;
n,m:longint;

procedure neww(var t:pnode);
begin
if t=nil then
begin
new(t);
t^.c:=0;
t^.lc:=nil;
t^.rc:=nil;
end;
end;

procedure insert(var t:pnode; l,r,x,y:longint);
var
i,j,k:longint;
mid:longint;

begin
with t^ do
begin
if c=0 then
begin
mid:=(l+r) div 2;
if (l=x) and (r=y)
then
begin
c:=1;
exit;
end;
if (l<=x) and (mid>=y)
then
begin
neww(lc);
insert(lc,l,mid,x,y);
exit;
end;
if (mid<=x) and (r>=y)
then
begin
neww(rc);
insert(rc,mid,r,x,y);
exit;
end;
neww(lc);
neww(rc);
insert(lc,l,mid,x,mid);
insert(rc,mid,r,mid,y);
end;
end;
end;

function find(t:pnode;l,r:longint):longint;
var
mid:longint;
begin
if t=nil then exit(0);
with t^ do
begin
mid:=(l+r) div 2;
if c=1 then exit(r-l);
exit(find(lc,l,mid)+find(rc,mid,r));
end;
end;

begin
readln(m);
readln(n);
fillchar(t,sizeof(t),0);
neww(t);
for i:=1 to n do
begin
readln(x,y);
insert(t,1,m,x,y);
end;
write(find(t,1,m));
end.

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: