线段树区间求和

题目:点击打开链接

代码:

program pro;
var
        tree:array[0..400000]of record a,b,l,r,lz:longint; sum:int64;  end;
        nn:array[0..200000]of longint;
        n,m,order,a,b,c,tot,i,j:longint;

procedure  maketree(l,r:longint);
var
        mid,now:longint;
begin
        inc(tot);
        now:=tot;
        tree[now].a:=l; tree[now].b:=r;
        if l=r then
        begin
                tree[now].sum:=nn[l];
                exit;
        end;

        mid:=(l+r)shr 1;
        tree[now].l:=tot+1;
        maketree(l,mid);
        tree[now].r:=tot+1;
        maketree(mid+1,r);
        tree[now].sum:=tree[tree[now].l].sum+tree[tree[now].r].sum;
end;

procedure gx(num:longint);
begin
        with tree[num] do
        begin
                inc(tree[l].lz,lz);
                inc(tree[r].lz,lz);
                inc(tree[l].sum,(tree[l].b-tree[l].a+1)*lz);
                inc(tree[r].sum,(tree[r].b-tree[r].a+1)*lz);
                lz:=0;
        end;
end;

procedure add(num,l,r,c:longint);
var
        mid:int64;
begin
        if tree[num].lz<>0 then gx(num);
        if (l<=tree[num].a)and(tree[num].b<=r) then
        begin
                inc(tree[num].lz,c);
                inc(tree[num].sum,(tree[num].b-tree[num].a+1)*c);
                exit;
        end;
        mid:=(tree[num].a+tree[num].b)shr 1;
        if l<=mid then add(tree[num].l,l,r,c);
        if r>mid then add(tree[num].r,l,r,c);
        tree[num].sum:=tree[tree[num].l].sum+tree[tree[num].r].sum;
end;

function find(num,l,r:longint):int64;
var
        mid,ans:int64;
begin
        if tree[num].lz<>0 then gx(num);
        if (l<=tree[num].a)and(tree[num].b<=r) then exit(tree[num].sum);

        ans:=0;
        mid:=(tree[num].a+tree[num].b)shr 1;
        if l<=mid then inc(ans,find(tree[num].l,l,r));
        if r>mid then inc(ans,find(tree[num].r,l,r));
        exit(ans);
end;

begin
assign(input,'xds_sum.in'); reset(input);
assign(output,'xds_sum.out'); rewrite(output);
        readln(n);
        for i:=1 to n do read(nn[i]);

        tot:=0;
        maketree(1,n);

        readln(m);
        for i:=1 to m do
        begin
                read(order);
                if order=1 then
                begin
                        readln(a,b,c);
                        add(1,a,b,c);
                end
                else
                begin
                        readln(a,b);
                        writeln(find(1,a,b));
                end;
        end;
close(input);
close(output);
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值