SSL P2648 线段树练习五

题目大意:
有N个格子,分别为1`N,M次修改,每次3个数Z,X,Y,
有2种情况:
Z=“M”时,将第X个格子加上Y。
Z=“C”时,统计区间[X,Y]的总和。

1≤N,M≤100000 1<=x<=y<=N
Z为M或者C

题解:
线段树:
1.可以发现,如果修改的话,每一次修改可以表示为在区间[l,l]加上一个数,这时候就用线段树。
2.每一次查询的时候,因为要修改的区间只有1个格子,所以这个区间一定是查询到的区间的一部分或者全部,这时候查询到区间[l,r]就给这个区间的总和加上修改的区间要添加的数,然后继续查询。
3.因为修改的区间都是线段树的最底端的几个点,所以不用做lazy,这对结果没有任何的影响,做了反而浪费时间。

var
     tree:array [0..500001] of longint;
     ans,i,n,m,x,y:longint;
     s:char;

procedure insert(p,l,r,a:longint);
var
      mid:longint;
begin
       tree[p]:=tree[p]+y;
       if l=r then exit;
       mid:=(l+r) div 2;
       if a<=mid then insert(p * 2,l,mid,a)
                 else insert(p*2+1,mid+1,r,a);
end;

procedure count(p,l,r,a,b:longint);
var
       mid:longint;
begin
       mid:=(l+r) div 2;
       if (l=a) and (r=b)
          then ans:=ans+tree[p]
          else begin
                    if b<=mid then count(p * 2,l,mid,a,b)
                              else if a>mid then count(p*2+1,mid+1,r,a,b)
                                            else begin
                                                       count(p * 2,l,mid,a,mid);
                                                       count(p*2+1,mid+1,r,mid+1,b);
                                                 end;
               end;
end;

begin
     readln(n);
     readln(m);
     for i:=1 to m do
         begin
              readln(s,x,y);
              if s='M' then insert(1,1,n,x)
                       else begin
                                 ans:=0;
                                 count(1,1,n,x,y);
                                 writeln(ans);
                            end;
         end;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值