SSL P2647 线段树练习四

题目大意:
在长为N的线段中(这条线段不算),加入M条线段[X,Y],最后查询某个线段[x,y]保证y=x+1。

1≤n,m≤100000,1≤x≤y≤n

题解:
就是一个线段树+lazy:
1.每次走的时候因为如果你二分到这一个区间就代表你插入的线段一定经过这个区间,这个区间的线段数+1,如果查询到的刚好跟插入的完全覆盖就直接加入lazy中然后退出,等下一次查询这个点带下去。
PS:因为查询的是[l,l+1]所以你二分注意是[l,mid],[mid,r]而不是[l,mid],[mid+1,r],如果那样的话[l,l+1]是搜不到的。
2.递归求解,因为是[l,mid],[mid,r]这样的二分,所以保证[l,l+1]一定不会分开成[l,l],[l+1,l+1],这个区间一定是个整体,是能被查询到的,所以暴力递归,查询到就直接输出= =。
再PS:
本来有貌似强迫症的我想求出全图任意一个区间[l,r]内的线段数的,可无奈做不出,想不出来……

var
     rp,tree:array [0..500001] of longint;
     i,j,n,m,s,x,y,z:longint;

procedure insert(p,l,r,a,b:longint);
var
      mid:longint;
begin
      mid:=(l+r) div 2;
      inc(tree[p]);
       if (l=a) and (r=b)
          then inc(rp[p])
          else begin
                    if r-l=1 then exit;
                    tree[p * 2]:=tree[p * 2]+rp[p];
                    tree[p*2+1]:=tree[p*2+1]+rp[p];
                    rp[p * 2]:=rp[p * 2]+rp[p];
                    rp[p*2+1]:=rp[p*2+1]+rp[p];
                    rp[p]:=0;
                    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 (l=x) and (r=y)
          then writeln(tree[p])
          else begin
                    if r-l=1 then exit;
                    tree[p * 2]:=tree[p * 2]+rp[p];
                    tree[p*2+1]:=tree[p*2+1]+rp[p];
                    rp[p * 2]:=rp[p * 2]+rp[p];
                    rp[p*2+1]:=rp[p*2+1]+rp[p];
                    rp[p]:=0;
                    if r<=mid then count(p * 2,l,mid)
                              else if l>=mid then count(p*2+1,mid,r)
                                            else begin
                                                       count(p * 2,l,mid);
                                                       count(p*2+1,mid,r);
                                                 end;
               end;
end;

begin
     readln(n,m);
     for i:=1 to m do
         begin
              readln(x,y);
              insert(1,1,n,x,y);
         end;
     readln(x,y);
     count(1,1,n);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值