Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 88353 | Accepted: 27469 | |
Case Time Limit: 2000MS |
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
Hint
题意:
给定一个数列A1,A2,…An以及Q个操作,按顺序执行这些操作。操作分2种
*给定l,r,x,对Al,Al+1,…,Ar同时加上x
*给出l,r,求Al,Al+1,…,Ar
分析:
和线段树的做法类似,树状数组也可以通过在每个节点上维护两个数据,高效地进行上述操作.
如果给区间[l, r)同时再加上x的话,每个节点的值将会如何变化呢?如果令
下面记sum(bit,i)为树状数组bit的前i项和。我们构建两个树状数组bit0和bit1,并且设
那么在[l,r)区间上同时加上x就可以看成是
*在bit0的l位置加上-x(l - 1)
*在bit1的l位置加上x
*在bit0的r+1位置加上xr
*在bit0的r+1位置加上-x
这四个操作。因此,查询和更新操作都可以在O(logn)时间里完成。
更一般的,如果操作得到的结果可以用i的n次多项式表示,那么就可以使用n+1个树状数组来进行维护了。
*T是操作的种类。第i个操作的T[i]是C的话,就是给区间同时加一个值,是Q的话则是查询一段的和。
*A,L,R都是以1为下标起点的。
#include <cstdio> using namespace std; typedef long long ll; const int maxn = 100000 + 10; int N, Q; ll A[maxn]; char T[maxn]; int L[maxn], R[maxn], X[maxn]; // BIT ll bit0[maxn], bit1[maxn]; ll sum(ll *b, int i) { ll s = 0; while (i > 0){ s += b[i]; i -= i & -i; } return s; } void add(ll *b, int i, int v) { while (i <= N){ b[i] += v; i += i & -i; } } void solve() { for (int i = 1; i <= N; i++){ scanf("%lld", &A[i]); add(bit0, i, A[i]); } for (int i = 0; i < Q; i++){ getchar(); scanf("%c", &T[i]); if (T[i] == 'C'){ scanf("%d%d%d", &L[i], &R[i], &X[i]); add(bit0, L[i], -X[i] * (L[i] - 1)); add(bit1, L[i], X[i]); add(bit0, R[i] + 1, X[i] * R[i]); add(bit1, R[i] + 1, -X[i]); } else { scanf("%d%d", &L[i], &R[i]); ll res = 0; res += sum(bit0, R[i]) + sum(bit1, R[i]) * R[i]; res -= sum(bit0, L[i] - 1) + sum(bit1, L[i] - 1) * (L[i] - 1); printf("%lld\n", res); } } } int main() { while (scanf("%d%d", &N, &Q) != EOF){ solve(); } return 0; }