题目链接:http://poj.org/problem?id=3468
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
Hint
The sums may exceed the range of 32-bit integers.
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 #include<map>
7 #include<set>
8 #include<vector>
9 using namespace std;
10 #define ll long long
11 const int inf=99999999;
12 const int mod=1e9+7;
13 const int maxn=100000+10;
14 typedef struct
15 {
16 int left;
17 int right;
18 ll int weight;
19 ll int lan;
20 } St;
21 St tree[maxn<<2];
22 int n,m;
23 int a,b;
24 ll int ans;
25 ll int num;
26 inline void build_tree(int k,int left,int right)//建树
27 {
28 tree[k].left=left;
29 tree[k].right=right;
30 if(left==right)
31 {
32 cin>>tree[k].weight;
33 return ;
34 }
35 int mid=(left+right)>>1;
36 build_tree(k<<1,left,mid);//左子树
37 build_tree(k<<1|1,mid+1,right);//右子树
38 tree[k].weight=tree[k<<1].weight+tree[k<<1|1].weight;//状态合并,该节点权重等于左子树加右子树权重
39 }
40 inline void lan_down(int k)//树懒标记下传
41 {
42 tree[k<<1].lan+=tree[k].lan;
43 tree[k<<1|1].lan+=tree[k].lan;
44 tree[k<<1].weight+=tree[k].lan*(tree[k<<1].right-tree[k<<1].left+1);
45 tree[k<<1|1].weight+=tree[k].lan*(tree[k<<1|1].right-tree[k<<1|1].left+1);
46 tree[k].lan=0;
47 }
48 inline void ask_point(int k)//单点查询
49 {
50 if(tree[k].left==tree[k].right)
51 {
52 ans=tree[k].weight;
53 return ;
54 }
55 if(tree[k].lan)
56 lan_down(k);
57 int mid=(tree[k].left+tree[k].right)>>1;
58 if(a<=mid)//a表示单点询问位置
59 ask_point(k<<1);//目标位置靠左,递归左孩子
60 else
61 ask_point(k<<1|1);//目标位置靠右,递归右孩子
62 }
63 inline void add_point(int k)//单点修改
64 {
65 if(tree[k].left==tree[k].right)
66 {
67 tree[k].weight+=num;//单点增加num
68 return ;
69 }
70 if(tree[k].lan)//树懒标记下传
71 lan_down(k);
72 int mid=(tree[k].left+tree[k].right)>>1;
73 if(a<=mid)
74 add_point(k<<1);
75 else
76 add_point(k<<1|1);
77 tree[k].weight=tree[k<<1].weight+tree[k<<1|1].weight;//状态合并
78 }
79 inline void ask_qujian(int k)//区间查询
80 {
81 if(tree[k].left>=a&&tree[k].right<=b)//包含了left,right当前区间,全加上
82 {
83 ans+=tree[k].weight;
84 return ;
85 }
86 if(tree[k].lan)//树懒标记下传
87 lan_down(k);
88 int mid=(tree[k].left+tree[k].right)>>1;
89 if(a<=mid)//递归查询左子区间
90 ask_qujian(k<<1);
91 if(b>mid)//递归查询右子区间
92 ask_qujian(k<<1|1);
93 }
94 inline void add_qujian(int k)//区间修改
95 {
96 if(tree[k].left>=a&&tree[k].right<=b)
97 {
98 tree[k].weight+=num*(tree[k].right-tree[k].left+1);
99 tree[k].lan+=num;
100 return ;
101 }
102 if(tree[k].lan)
103 lan_down(k);
104 int mid=(tree[k].left+tree[k].right)>>1;
105 if(a<=mid)
106 add_qujian(k<<1);
107 if(b>mid)
108 add_qujian(k<<1|1);
109 tree[k].weight=tree[k<<1].weight+tree[k<<1|1].weight;//状态合并
110 }
111 int main()
112 {
113 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
114 cin>>n>>m; //n个节点,m个操作
115 build_tree(1,1,n);//建树
116 char op;
117 for(int i=0;i<m;i++)
118 {
119 cin>>op>>a>>b;
120 if(op=='Q')
121 {
122 ans=0;
123 ask_qujian(1);//区间查询
124 cout<<ans<<endl;
125 }
126 else if(op=='C')
127 {
128 cin>>num;
129 add_qujian(1);//区间修改
130 }
131 }
132 return 0;
133 }