A Simple Problem with Integers(线段树区间更新模板题)

A Simple Problem with Integers
Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u
Submit Status

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.
 
  1 //Memory: 4324 KB        Time: 1594 MS
  2 //Language: C++        Result: Accepted
  3 
  4 #include <iostream>
  5 #include <cstdio>
  6 
  7 using namespace std;
  8 
  9 typedef long long ll;
 10 #define ls rt<<1
 11 #define rs rt<<1|1
 12 
 13 const int sz = 100001;
 14 struct Tree
 15 {
 16      ll sum, inc;
 17 }t[sz<<2];
 18 ll d, ans;
 19 
 20 void build(const int left, const int right, const int rt)
 21 {
 22     t[rt].inc = 0;
 23     if(right == left)
 24     {
 25         scanf("%I64d", &t[rt].sum);
 26         return ;
 27     }
 28     int mid = (right + left) >> 1;
 29     build(left, mid, ls);
 30     build(mid + 1, right, rs);
 31     t[rt].sum = t[ls].sum + t[rs].sum;
 32     return ;
 33 }
 34 
 35 void update(const int l, const int r, const int from, const int to, const int rt)
 36 {
 37     if(from <= l && r <= to)
 38     {
 39         t[rt].inc += d;
 40         t[rt].sum += ((ll)(r - l + 1) * d);  //(1)
 41         return ;
 42     }
 43     if(t[rt].inc)
 44     {
 45         t[ls].inc += t[rt].inc;
 46         t[rs].inc += t[rt].inc;
 47         t[ls].sum += ((ll)((r - l + 2) >> 1) * t[rt].inc);  //(2)
 48         t[rs].sum += ((ll)((r - l + 1) >> 1) * t[rt].inc);
 49         t[rt].inc = 0;
 50     }
 51     int mid = (l + r) >> 1;
 52     if(from <= mid) update(l, mid, from, to, ls);
 53     if(to > mid) update(mid + 1, r, from, to, rs);
 54     t[rt].sum = t[ls].sum + t[rs].sum;
 55     return ;
 56 }
 57 
 58 void query(const int l, const int r, const int from, const int to, const int rt)
 59 {
 60     if(from <= l && r <= to)
 61     {
 62         ans += t[rt].sum;
 63         return ;
 64     }
 65     if(t[rt].inc)
 66     {
 67         t[ls].inc += t[rt].inc;
 68         t[rs].inc += t[rt].inc;
 69         t[ls].sum += ((ll)((r - l + 2) >> 1) * t[rt].inc);
 70         t[rs].sum += ((ll)((r - l + 1) >> 1) * t[rt].inc);
 71         t[rt].inc = 0;
 72     }
 73     int mid = (l + r) >> 1;
 74     if(from <= mid) query(l, mid, from, to, ls);
 75     if(to > mid) query(mid + 1, r, from, to, rs);
 76     return ;
 77 }
 78 
 79 int main()
 80 {
 81     int q, n, a, b;
 82     char cmd;
 83     while(scanf("%d %d", &n, &q) != EOF)
 84     {
 85         build(1, n, 1);
 86         while(q--)
 87         {
 88             cin >> cmd;
 89             if(cmd == 'Q')
 90             {
 91                 scanf("%d %d", &a, &b);
 92                 ans = 0;
 93                 query(1, n, a, b, 1);
 94                 printf("%I64d\n", ans);
 95             }
 96             else
 97             {
 98                 scanf("%d %d %I64d", &a, &b, &d);
 99                 update(1, n, a, b, 1);
100             }
101         }
102     }
103     return 0;
104 }
105 /*
106 (1) *d而非*t[rt].inc,因为t[rt].inc是保存rt的儿子的更新数据的,到达rt的更新是d
107 (2) *t[rt].inc而非*t[ls].inc,因为t[ls].inc是保存ls的儿子的更新数据的。到达ls的更新是
108 t[rt].inc.(r - l + 2) >> 1是ls的左儿子的区间长度,(r - l + 1) >> 1是右儿子的区间长度。
109 实际上(r - l + 2) >> 1是(r - l + 1) / 2.0的向上取整。注意由于在build中,mid归于左儿子,
110 故左儿子的区间长度>=右儿子区间长度
111 */

 

posted on 2013-05-11 09:43  铁树银花  阅读(250)  评论(0编辑  收藏  举报

导航