【POJ3468】【树状数组区间修改】A Simple Problem with Integers

Description

You have N integers, A1A2, ... , 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 A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+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

The sums may exceed the range of 32-bit integers.

Source

【分析】

以前一直以为树状数组只能单点修改,区间询问,今天算是见识到了树状数组的区间修改了。

不说多的了,很巧妙的感觉,对于一个修改操作(a,b,c),将[a,b]区间整体加上一个c

可以把它拆开成两个部分(a,n,c),和(b + 1,n,-c),这个时候就好做了,用两个树状数组。

一个树状数组记录从修改点开始一直到结束所增加的所有量,及c*(n-a+1)。另一个记录下增量值c。

那么对于一个在a点右边而在b点左边的点x,它所得到的增量为c*(n-a+1) - c*(n-x)。很好维护了。

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <algorithm>

 4 #include <cstring>

 5 #include <vector>

 6 #include <utility>

 7 #include <iomanip>

 8 #include <string>

 9 #include <cmath>

10 #include <map>

11 

12 const int MAXN = 100000 + 10; 

13 const int MAX = 32000 + 10; 

14 using namespace std;

15 typedef long long ll;

16 int n, m;

17 ll sum[MAXN];//记录原始序列

18 ll C[2][MAXN]; 

19 

20 int lowbit(int x){return x&-x;}

21 ll get(int k, int x){

22     ll cnt = 0;

23     while (x > 0){

24           cnt += C[k][x];

25           x -= lowbit(x);

26     }

27     return cnt;

28 }

29 void add(int k, int x, ll val){

30      while (x <= n){

31            C[k][x] += val;

32            x += lowbit(x); 

33      }

34      return ;

35 }

36 void work(){

37      memset(C, 0, sizeof(C));//0记录总值、1录增量 

38      sum[0] = 0;

39      scanf("%d%d", &n, &m);

40      for (int i = 1; i <= n; i++){

41          scanf("%lld", &sum[i]);

42          sum[i] += sum[i - 1];

43      }

44      for (int i = 1; i <= m; i++){

45          char str[2];

46          scanf("%s", str);

47          if (str[0] == 'Q'){

48             int l, r;

49             scanf("%d%d", &l, &r);

50             printf("%lld\n", sum[r] - sum[l - 1] +(get(0, r) - get(1, r) * (n - r)) - (get(0, l - 1) - get(1, l - 1) * (n - l + 1)));

51          }else{

52                int l, r;

53                ll x;

54                scanf("%d%d%lld", &l, &r, &x);

55                add(0, l, (n - l + 1) * x);

56                add(0, r + 1, (n - r) * (-x));

57                add(1, l, x);

58                add(1, r + 1, -x); 

59          }

60      }

61      //printf("\n%d\n", get(0, 10));

62 }

63 

64 int main(){

65     int T;

66     #ifdef LOCAL

67     freopen("data.txt",  "r",  stdin);

68     freopen("out.txt",  "w",  stdout); 

69     #endif

70     work();

71     return 0;

72 }
View Code

 

你可能感兴趣的:(Integer)