问题描述
在平面内有一条长度为n的线段(也算一条线段),可以对进行以下2种操作:
1 x y 把从x到y的再加一条线段
2 x 查询从x到x+1有多少条线段
输入
第一行两个数n,m
表示长度为n的线段
接下来的m行读入x,y
表示在[x,y]的区间中加入一条线段
最后一行两个数x,y
输出x到y这一个区间中的线段数
保证x+1=y
输出
输出线段数目
样例输入
7 5
2 3
2 5
2 4
4 5
2 4
2 4
样例输出
3
算法讨论
将线段树的域定义为完全覆盖当前节点的线段数,当当前节点被完全覆盖时就不再往下走。统计时从根节点一直加到询问的节点上,就为叠加线段数。
const
maxn=50000;
var
t:array[1..maxn,1..3] of longint;
i,n,m,x,y,s,o,p1:longint;
function count(p:longint):longint;
var
s:longint;
begin
s:=0;
while p>0 do
begin
inc(s,t[p,3]);
p:=p div 2
end;
count:=s
end;
procedure insert(p,a,b:longint);
var
m:longint;
begin
m:=(t[p,1]+t[p,2]) div 2;
if (t[p,1]=a) and (t[p,2]=b)
then inc(t[p,3])
else if b<=m
then insert(p*2,a,b)
else if a>=m
then insert(p*2+1,a,b)
else begin
insert(p*2,a,m);
insert(p*2+1,m,b)
end;
end;
procedure create(p:longint);
var
m:longint;
begin
if t[p,2]-t[p,1]>1
then begin
m:=(t[p,1]+t[p,2]) div 2;
t[p*2,1]:=t[p,1]; t[p*2,2]:=m;
t[p*2+1,1]:=m; t[p*2+1,2]:=t[p,2];
create(p*2);
create(p*2+1)
end;
end;
procedure find(p,a,b:longint);
var
m:longint;
begin
m:=(t[p,1]+t[p,2]) div 2;
if (t[p,1]=a) and (t[p,2]=b)
then p1:=p
else if m>=b
then find(2*p,a,b)
else if m<=a
then find(2*p+1,a,b)
else begin
find(2*p,a,m);
find(2*p+1,m,b);
end;
end;
begin
read(n,m);
t[1,1]:=1; t[1,2]:=n;
create(1);
for i:=1 to m do
begin
readln(x,y);
insert(1,x,y)
end;
read(x,y);
find(1,x,y);
s:=count(p1);
write(s)
end.
Pixiv ID:17235752