题目大意:
如题,已知一个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.