POJ 3468

C - A Simple Problem with Integers
Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u
Appoint description: 

Description

给出了一个序列,你需要处理如下两种询问。

"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。

"Q a b" 询问[a, b]区间中所有值的和。

Input

第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.

第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。

接下来Q行询问,格式如题目描述。

Output

对于每一个Q开头的询问,你需要输出相应的答案,每个答案一行。

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

题意:中文题

思路:这种 n*n 的查询更新,肯定用线段树。但是不能单点更新,如果单点更新的话,相当于将区间内所有点都递归到树的最后一层再更新。因此要利用区间更新,大致思路是:1,对每个结点,除了设置 sum 变量之外,再存一个 add 变量用来整个区间被更新的次数。递归过程中如果碰到 ll == l && rr == r 的情况,不必向下更新,直接更新这个区间的 add。 2,每次递归 update 时要更新当前 sum。(更新的必要性也有写到) 3,查询时又上到下传递 add 参数,最后要 return sum+(区间长度)*addd; 

具体有些细节注释中写到了。

代码:

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 struct Node{
 6     int l,r;
 7     long long add;
 8     long long sum;
 9 }node[100000*4+5];
10 int a[100005];
11 
12 void build(int id,int l,int r){
13     node[id].l = l;
14     node[id].r = r;
15     node[id].add = 0;
16 
17     if(l == r){
18         node[id].sum = a[l];
19         return ;
20     }
21     int mid = (l+r)>>1;
22     build(id*2,l,mid);
23     build(id*2+1,mid+1,r);
24 
25     node[id].sum = node[id*2].sum+node[id*2+1].sum;
26 }
27 long long query(int id,int l,int r,long long c){        //c为到该层为止,包含该层子区间的结点共更新了多少次。每次递归需累加
28     int ll = node[id].l;
29     int rr = node[id].r;
30     int mid = (ll+rr)>>1;
31     int addd = node[id].add;
32 
33     //if(ll == rr)  return node[id].sum + c+addd;
34     if(ll == l && rr == r)
35         return node[id].sum +  (r-l+1)*(c);
36     if(r <= mid)
37         return query(id*2,l,r,c+addd);
38     else if(l > mid)
39         return query(id*2+1,l,r,c+addd);
40     else
41         return query(id*2,l,mid,c+addd) + query(id*2+1,mid+1,r,c+addd);
42 }
43 void update(int id,int l,int r,int c){
44     int ll = node[id].l;
45     int rr = node[id].r;
46     int mid = (ll+rr)>>1;
47 
48     node[id].sum += (r-l+1)*c;      //下层区间更新了,但是该层的add未更新,所以要修改该层的sum
49     if(ll == l && rr == r){     //用更新区间代替点
50         node[id].add += c;
51         return ;
52     }
53     if(r <= mid)
54         update(id*2,l,r,c);
55     else if(l > mid)
56         update(id*2+1,l,r,c);
57     else{
58         update(id*2,l,mid,c);
59         update(id*2+1,mid+1,r,c);
60     }
61 }
62 
63 int main()
64 {
65     ios_base::sync_with_stdio(0);
66     cin.tie(0);
67     int n,m;
68     while(cin>>n>>m){
69         for(int i = 1;i <= n;i ++)  cin>>a[i];
70 
71         build(1,1,n);
72         string s;
73         int ai,bi,ci;
74         for(int i = 1;i <= m;i ++){
75             cin>>s;
76             if(s[0] == 'Q'){
77                 cin>>ai>>bi;
78                 long long ans = query(1,ai,bi,0);
79                 cout<<ans<<endl;
80             }
81             if(s[0] == 'C'){
82                 cin>>ai>>bi>>ci;
83                 update(1,ai,bi,ci);
84             }
85         }
86     }
87     return 0;
88 }
View Code


原文地址:https://www.cnblogs.com/Jstyle-continue/p/6351937.html