poj3468 A Simple Problem with Integers——线段树的应用
A Simple Problem with Integers
| Time Limit: 5000MS | Memory Limit: 131072K | |
| Total Submissions: 16883 | Accepted: 4349 | |
| Case Time Limit: 2000MS | ||
Description
You haveNintegers,A1,A2, ... ,AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbersNandQ. 1 ≤N,Q≤ 100000.
The second line containsNnumbers, the initial values ofA1,A2, ... ,AN. -1000000000 ≤Ai≤ 1000000000.
Each of the nextQlines represents an operation.
"Cabc" means addingcto each ofAa,Aa+1, ... ,Ab. -10000 ≤c≤ 10000.
"Qab" means querying the sum ofAa,Aa+1, ... ,Ab.
Output
You need to answer allQcommands in order. One answer in a line.
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9 15
Hint
The sums may exceed the range of 32-bit integers.
Source
POJ Monthly--2007.11.25, Yang Yi
题目大意:给出一个区间,1~n,有m个操作,每一个操作可能是:“I”——“a,b,c”——插入——在区间中的a到b每一个数都加一个数c;“Q”——“a,b”——求和——输出区间a到b的和。
小结:看到区间问题,首先应该想到线段树,而求和又是线段树的基本操作。题目中要求比较不同的就是对于区间的每一个数都加一个数,如果直接对每一个数都进行一次加法运算,那么效率将是很低的。这里应用到一种称之为“lazy”的思想:对于一个区间,给它标记一个数值data,比如题目中的区间每一个数的增量,这个值就代表区间的每一个值都需要加上这个值。当我们需要处理这个区间时,就将这个数值data分配给两个儿子,而自己的data值变成0.对于其他的以区间为单位的基本操作也可以采用这种lazy思想,需要拆分时将它分开传递给两份儿子。
type
ji=^rec;
rec=record
sum,add:int64;
l,r:longint;
lson,rson:ji;
end;
var
a:ji;
ch:char;
b:array[0..100005] of int64;
i,j,k,m,n,s,t:longint;
procedure build(var a:ji; l,r:longint);
begin
new(a); a^.l:=l; a^.r:=r;
if r>l then
begin
build(a^.lson,l,(l+r)>>1);
build(a^.rson,(l+r)>>1+1,r);
a^.add:=0;
a^.sum:=a^.lson^.sum+a^.rson^.sum;
end
else
begin
a^.sum:=b[l];
a^.add:=0;
a^.lson:=nil;
a^.rson:=nil;
end;
end;
procedure insert(var a:ji; l,r,s:longint);
var
mid:longint;
begin
if (a^.l>=l)and(a^.r<=r) then
begin
inc(a^.add,s);
exit;
end;
mid:=(a^.l+a^.r)>>1;
if l<=mid then insert(a^.lson,l,r,s);
if r>mid then insert(a^.rson,l,r,s);
a^.sum:=a^.lson^.sum+a^.lson^.add*(a^.lson^.r-a^.lson^.l+1);
inc(a^.sum,a^.rson^.sum+a^.rson^.add*(a^.rson^.r-a^.rson^.l+1));
end;
function count(var a:ji; l,r:longint):int64;
var
mid:longint;
ans:int64;
begin
ans:=0;
if (l<=a^.l)and(r>=a^.r) then
begin
inc(ans,a^.sum+a^.add*(a^.r-a^.l+1));
exit(ans);
end;
if a^.lson<>nil then inc(a^.lson^.add,a^.add);
if a^.rson<>nil then inc(a^.rson^.add,a^.add);
a^.add:=0;
mid:=(a^.l+a^.r)>>1;
if l<=mid then ans:=ans+count(a^.lson,l,r);
if r>mid then ans:=ans+count(a^.rson,l,r);
a^.sum:=a^.lson^.sum+a^.rson^.sum+a^.lson^.add*(a^.lson^.r-a^.lson^.l+1);
inc(a^.sum,a^.rson^.add*(a^.rson^.r-a^.rson^.l+1));
exit(ans);
end;
begin
readln(n,m);
for i:=1 to n do read(b[i]); readln;
build(a,1,n);
for i:=1 to m do
begin
read(ch,s,t);
if ch='C' then
begin
read(k);
insert(a,s,t,k);
end
else
begin
writeln(count(a,s,t));
end;
readln;
end;
end.
浙公网安备 33010602011771号