MY*****

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

题目大意:给出一个区间,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.

posted on 2011-01-22 18:06  reflec94  阅读(426)  评论(0编辑  收藏  举报

导航