洛谷 P3372【模板】线段树 1

题目大意:
如题,已知一个N个数的数列,
你需要进行M次操作,操作有下面两种:
s=1,将某区间每一个数加上x
s=2,求出某区间每一个数的和

时间限制:1000ms
空间:128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
数据保证不超过max(int64)/max(longlong)
这里写图片描述

题解:
注意pascal要开int64,C++要开longlong。
线段树,注意要做lazy标记~。

时间复杂度:O(Log N)

var
     tree:array [0..300000] of int64;
     bp:array [0..300000] of int64;
     i,j,n,m,s,x,y,z:longint;
     ans:int64;

procedure insert(p,l,r,a,b:longint);
var
      mid:longint;
begin
      mid:=(l+r) div 2;
       if (l=a) and (r=b)
          then begin
                    tree[p]:=tree[p]+(r-l+1)*z;
                    bp[p]:=bp[p]+z;
               end
          else begin
                    tree[p * 2]:=tree[p * 2]+(mid-l+1)*bp[p];
                    tree[p*2+1]:=tree[p*2+1]+(r-mid)*bp[p];
                    bp[p * 2]:=bp[p * 2]+bp[p];
                    bp[p*2+1]:=bp[p*2+1]+bp[p];
                    bp[p]:=0;
                    if b<=mid then insert(p * 2,l,mid,a,b)
                              else if a>mid then insert(p*2+1,mid+1,r,a,b)
                                            else begin
                                                       insert(p * 2,l,mid,a,mid);
                                                       insert(p*2+1,mid+1,r,mid+1,b);
                                                 end;
                    tree[p]:=tree[p * 2]+tree[p*2+1];
               end;
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
                    tree[p * 2]:=tree[p * 2]+(mid-l+1)*bp[p];
                    tree[p*2+1]:=tree[p*2+1]+(r-mid)*bp[p];
                    bp[p * 2]:=bp[p * 2]+bp[p];
                    bp[p*2+1]:=bp[p*2+1]+bp[p];
                    bp[p]:=0;
                    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,m);
     for i:=1 to n do
         begin
              read(z);
              insert(1,1,n,i,i);
         end;
     readln;
     for i:=1 to m do
         begin
              read(s);
              if s=1 then
                 begin
                     read(x,y,z);
                     insert(1,1,n,x,y);
                 end
              else if s=2 then
                      begin
                           read(x,y);
                           ans:=0;
                           count(1,1,n,x,y);
                           writeln(ans);
                      end;
              readln;
         end;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值