POJ-3468 A Simple Problem with Integers ( 线段树 )

题目链接: http://poj.org/problem?id=3468

Description

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

询问区间和并对区间进行操作。
对区间操作是不能点更新,应该区间更新,不然会超时 例如区间(1,10),我要对(3,8)进行操作,点更新需要进行(1,5),(1,3),(3,3),(4,5),(4,4),(5,5),(6,10),(6,8),(6,7),(6,6),(7,7),(8,8)共12步,而区间操作只需要(1,5),(1,3),(3,3),(4,5),(6,10),(6,8)共6步,而这只是一种简单的情况。
进行区间操作需要在节点加入一个参数add,用来记录该区间每个元素的增值以避免点更新。

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 class node{
 6 public:
 7     int l, r;
 8     long long v, add; //v为该区间的和,并用add记录加在该区间上的值
 9     node *left, *right;
10 };
11 long long num[100005];
12 
13 node *Creat( int z, int y ){
14     node *root = new node;
15     root->l = z;
16     root->r = y;
17     root->add = 0;
18     root->left = NULL;
19     root->right = NULL;
20     if( z == y ){
21         root->v = num[z];
22         return root;
23     }
24 
25     int mid = ( z + y ) >> 1;
26     root->left = Creat( z, mid );
27     root->right = Creat( mid + 1, y );
28 
29     root->v = root->left->v + root->right->v;
30 
31     return root;
32 }
33 
34 void Insert( int z, int y, long long n, node *p ){
35     if( z == p->l && y == p->r ){
36         p->add += n;
37         return;
38     }
39 
40     p->v += ( y - z + 1 ) * n;
41 
42     int mid = ( p->l + p->r ) >> 1;
43 
44     if( y <= mid ) Insert( z, y, n, p->left );
45     else if( z > mid ) Insert( z, y, n, p->right );
46     else{
47         Insert( z, mid, n, p->left );
48         Insert( mid +1, y, n, p->right );
49     }
50 }
51 
52 long long Ask( int z, int y,node *p ){
53     long long ans = 0;
54 
55     if( z == p->l && y == p->r )
56         return p->v + p->add * ( y - z +1 );
57 
58     ans += p->add * ( y - z + 1 );
59     
60     int mid = ( p->l + p->r ) >> 1;
61 
62     if( y <= mid ) ans += Ask( z, y, p->left );
63     else if( z > mid ) ans += Ask( z, y, p->right );
64     else
65         ans += Ask( z, mid, p->left ) + Ask( mid + 1, y, p->right );
66     
67     return ans;
68 }
69 
70 int main(){
71     ios::sync_with_stdio( false );
72 
73     int N, Q;
74     cin >> N >> Q;
75 
76     for( int i = 1; i <= N; i++ )
77         cin >> num[i];
78 
79     node *root = Creat( 1, N );
80 
81     int a, b;
82     long long c;
83     char k;
84     for( int i = 1; i <= Q; i++ ){
85         cin >> k;
86         
87         if( k == 'C' ){
88             cin >> a >> b >> c;
89             Insert( a, b, c, root);
90         }
91 
92         else{
93             cin >> a >> b;
94             cout << Ask( a, b, root ) << endl;
95         }
96     }
97 
98     return 0;
99 }