您的位置:首页 > 其它

洛谷 P3372【模板】线段树 1

2017-04-15 10:56 387 查看
题目大意:

如题,已知一个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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: