树状数组区间修改 poj3468(A Simple Problem with Integers)

http://poj.org/problem?id=3468

题意:

给出n,q <1e6

n个整数-1000000000 ≤ Ai ≤ 1000000000

q个命令:"C a b c"a到b区间全部+c 或 "Q a b" 输出a到b区间的和

-----------------------------------------------------------

树状数组的区间修改+区间查询:

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <functional>
 9 #define INF 0x3f3f3f3f
10 #define N 100010
11 #define lowbit(a) ((a)&(-a))
12 using namespace std;
13 typedef long long ll;
14 
15 ll sum[N], d[N], di[N];
16 
17 //区间修改
18 void _update(ll *arr, ll pos, ll x){
19     while (pos <= N){
20         arr[pos] += x;
21         pos += lowbit(pos);
22     }
23 }
24 void add(ll l, ll r, ll x){
25     _update(d, l, x);
26     _update(d, r + 1, -x);
27     _update(di, l, x*l);
28     _update(di, r + 1, -x*(r + 1));
29 }
30 //区间查询
31 ll _sum(ll *arr, ll pos){
32     ll temp = 0ll;
33     while (pos){
34         temp += arr[pos];
35         pos -= lowbit(pos);
36     }
37     return temp;
38 }
39 ll getsum(ll pos){
40     return sum[pos] + _sum(d, pos)*(pos + 1) - _sum(di, pos);
41 }
42 
43 int main(){
44     ll l, r, x;
45     char ch;
46     int n, m;
47 
48     while (~scanf("%d %d", &n, &m)){
49         sum[0] = 0;
50         for (int i = 1; i <= n; i++){
51             scanf("%lld", &x);
52             sum[i] = sum[i - 1] + x;
53         }
54         memset(d, 0, sizeof(d));
55         memset(di, 0, sizeof(di));
56         while (m--){
57             while ((ch = getchar()) == '\n');
58             if (ch == 'Q'){
59                 scanf("%lld %lld", &l, &r);
60                 printf("%lld\n", getsum(r) - getsum(l - 1));
61             }
62             else{
63                 scanf("%lld %lld %lld", &l, &r, &x);
64                 add(l, r, x);
65             }
66         }
67     }
68     return 0;
69 }

 

posted @ 2018-03-17 11:52  心照不必宣  阅读(99)  评论(0)    收藏  举报