【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
", 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("
%d
", 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
原文地址:https://www.cnblogs.com/hoskey/p/4320386.html