模板:树状数组(带区间修改和区间更新)

转自:http://blog.csdn.net/qq_21841245/article/details/43956633

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 #define N 200010
 6 typedef long long LL;
 7 
 8 LL bit[2][N], sum[N], a[N], maxn;
 9  // bit[0]维护delta[x]. bit[1]维护delta[x]*x
10  // sum[i] = a[1]+...+a[i] + delta[1]*i + delta[2]*(i - 1) + delta[3]*(i - 2)+...+delta[i]*1   // a[i]为原始数组
11  //       = sigma( a[x] ) + sigma( delta[x]  *  (i + 1 - x) )
12  //       = sigma( a[x] ) + (i + 1) * sigma( delta[x] ) - sigma( delta[x] * x )
13 int lowbit(int x) { return x & (-x); }
14 void update(int i, int x, int w) { while(x <= maxn) bit[i][x] += w, x += lowbit(x); }
15 LL query(int i, int x) { LL ans = 0; while(x) ans += bit[i][x], x -= lowbit(x); return ans; }
16 void Add(int l, int r, int w) {
17     update(0, l, w); update(0, r + 1, -w);
18     update(1, l, w * l); update(1, r + 1, -w * (r + 1));
19 }
20 LL Sum(int l, int r) {
21     LL suml = sum[l - 1] + l * query(0, l - 1) - query(1, l - 1);
22     LL sumr = sum[r] + (r + 1) * query(0, r) - query(1, r);
23 //    printf("sum : %d, %d
", suml, sumr);
24     return sumr - suml;
25 }
26 
27 int main() {
28     int n, q;
29     scanf("%d", &n);
30     for(int i = 1; i <= n; i++) scanf("%d", &a[i]), sum[i] = sum[i-1] + a[i], Add(i, i, a[i]);
31     scanf("%d", &q); maxn = n;
32     memset(bit, 0, sizeof(bit));
33     while(q--) {
34         int a, b, c, d;
35         scanf("%d", &a);
36         if(a == 1) {
37             scanf("%d%d%d", &b, &c, &d);
38             Add(b, c, d);
39         } else {
40             scanf("%d%d", &b, &c);
41             printf("%lld
", Sum(b, c));
42         }
43     }
44     return 0;
45 }
原文地址:https://www.cnblogs.com/fightfordream/p/6285474.html