题目大意:
N长度的桌子上零散地放着M个不同颜色的盒子,桌子的后方是一堵墙。给出每个箱子的左端跟右端,问从桌子前方可以看到多少个盒子?假设人站得足够远(输入时,由底向上,从左到右)。
1<=n<=100000,1<=m<=100000,保证坐标[l,r]范围为[1,n].
题解:
线段树:
跟ZJU的那道题一样,
http://blog.csdn.net/gx_man_vip/article/details/70160195
不过把记录数量变成了记录是否存在。
var
ans,tree:array [0..300000] of longint;
sum,i,n,m,a,b,c:longint;
procedure insert(p,l,r,a,b:longint);
var
mid:longint;
begin
mid:=(l+r) div 2;
if (a=l) and (b=r)
then tree[p]:=c
else begin
if tree[p]<>-1
then begin
tree[p * 2]:=tree[p];
tree[p*2+1]:=tree[p];
tree[p]:=-1;
end;
if b<=mid then insert(p*2,l,mid,a,b)
else if a>=mid then insert(p*2+1,mid,r,a,b)
else begin
insert(p * 2,l,mid,a,mid);
insert(p*2+1,mid,r,mid,b);
end;
end;
end;
procedure count(p,l,r:longint);
var
mid:longint;
begin
mid:=(l+r) div 2;
if tree[p]=-2
then begin
c:=-2;
exit;
end
else if (tree[p]<>c) and (tree[p]<>-1)
then begin
c:=tree[p];
ans[c]:=1;
end
else if (r-l=1) and (c=tree[p])
then exit
else if tree[p]=-1
then begin
count(p * 2,l,mid);
count(p*2+1,mid,r);
end;
end;
procedure print;
begin
for i:=1 to n do
if ans[i]=1 then inc(sum);
writeln(sum);
end;
begin
for i:=0 to 300000 do tree[i]:=-2;
readln(n);
readln(m);
for i:=1 to m do
begin
readln(a,b);
c:=i;
insert(1,1,n,a,b);
end;
c:=-3;
count(1,1,n);
print;
end.