poj3468 A Simple Problem with Integers(线段树/树状数组)
Description
You have N integers, 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 numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands 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
Source
上图最后一行打错了,应该似乎求a[l]到a[r]的和。
线段树做法太裸,直接贴代码:
1 program rrr(input,output); 2 type 3 treetype=record 4 l,r:longint; 5 sum,d:int64; 6 end; 7 var 8 a:array[0..400040]of treetype; 9 c:array[0..100010]of longint; 10 n,q,i,x,y,d:longint; 11 ch:char; 12 procedure build(k,l,r:longint); 13 var 14 mid,i:longint; 15 begin 16 a[k].l:=l;a[k].r:=r;a[k].d:=0; 17 if l=r then begin a[k].sum:=c[l];exit; end; 18 mid:=(l+r)>>1;i:=k+k; 19 build(i,l,mid);build(i+1,mid+1,r); 20 a[k].sum:=a[i].sum+a[i+1].sum; 21 end; 22 procedure pushdown(k:longint); 23 var 24 i:longint; 25 begin 26 if a[k].l=a[k].r then a[k].d:=0; 27 if a[k].d=0 then exit; 28 i:=k+k;a[i].sum:=a[i].sum+(a[i].r-a[i].l+1)*a[k].d;a[i].d:=a[i].d+a[k].d; 29 inc(i);a[i].sum:=a[i].sum+(a[i].r-a[i].l+1)*a[k].d;a[i].d:=a[i].d+a[k].d; 30 a[k].d:=0; 31 end; 32 function ask(k:longint):int64; 33 var 34 mid:longint; 35 ans:int64; 36 begin 37 pushdown(k); 38 if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].sum); 39 mid:=(a[k].l+a[k].r)>>1;ans:=0; 40 if x<=mid then ans:=ask(k+k); 41 if mid<y then ans:=ans+ask(k+k+1); 42 exit(ans); 43 end; 44 procedure change(k:longint); 45 var 46 mid,i:longint; 47 begin 48 pushdown(k); 49 if (x<=a[k].l) and (a[k].r<=y) then begin a[k].sum:=a[k].sum+d*(a[k].r-a[k].l+1);a[k].d:=d;exit; end; 50 mid:=(a[k].l+a[k].r)>>1;i:=k+k; 51 if x<=mid then change(i); 52 if mid<y then change(i+1); 53 a[k].sum:=a[i].sum+a[i+1].sum; 54 end; 55 begin 56 assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output); 57 readln(n,q); 58 for i:=1 to n do read(c[i]);readln; 59 build(1,1,n); 60 for i:=1 to q do 61 begin 62 read(ch,x,y); 63 if ch='Q' then writeln(ask(1)) 64 else begin read(d);change(1); end; 65 readln; 66 end; 67 close(input);close(output); 68 end.
下面是树状数组做法:
代码(实测比线段树快1倍):
1 program rrr(input,output); 2 var 3 a,b:array[0..100010]of int64; 4 n,q,i:longint; 5 c:char; 6 ans,x,y,z:int64; 7 procedure adda(k,x:int64); 8 begin 9 while k<=n do begin a[k]:=a[k]+x;k:=k+k and (-k); end; 10 end; 11 procedure addb(k,x:int64); 12 begin 13 while k<=n do begin b[k]:=b[k]+x;k:=k+k and (-k); end; 14 end; 15 function suma(k:longint):int64; 16 begin 17 ans:=0; 18 while k>0 do begin ans:=ans+a[k];k:=k-k and (-k); end; 19 exit(ans); 20 end; 21 function sumb(k:longint):int64; 22 begin 23 ans:=0; 24 while k>0 do begin ans:=ans+b[k];k:=k-k and (-k); end; 25 exit(ans); 26 end; 27 begin 28 assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output); 29 readln(n,q); 30 fillchar(a,sizeof(a),0); 31 fillchar(b,sizeof(b),0); 32 for i:=1 to n do begin read(z);adda(i,z); end;readln; 33 for i:=1 to q do 34 begin 35 read(c,x,y); 36 if c='Q' then writeln(suma(y)+sumb(y)*y-suma(x-1)-sumb(x-1)*(x-1)) 37 else begin read(z);adda(x,-z*(x-1));addb(x,z);adda(y,z*y);addb(y,-z); end; 38 readln; 39 end; 40 close(input);close(output); 41 end.