Description
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of op
eration 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.
1.给[a ,b]整体上加上一个常数c。
2.查询[a ,b]区间的和。
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. The sums may exceed the range of 32-bit integers
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
分析
利用模板2里的差分数组,我们可以快速地修改区间。
那么在使用差分数组的情况下如何快速查询区间值呢?
我们来推导一个式子
首先,查询区间值其实就是查询区间内的每一个元素,而在我们的差分数组中每个元素等于对应的前缀和
所以我们需要求的区间值就变成了差分数组前若干个前缀和之和
写出来就是这样
我们进行一下变形(这步要看懂)
通过观察我们可以发现后面那一堆其实都是(i - 1) * a[ i ]
写成求和符号
那么这道题就很清晰了
我们只需要再使用一个树状数组存下(i - 1) * a[ i ]就可以快速计算后面那一坨
然后就可以算出区间值了
代码
#include<iostream>
#include<cstdio>
using namespace std;
long long n, q;
long long a[100010];
long long tree1[100010];
long long tree2[100010];
inline long long read() {
long long x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
return x * f;
}
long long ask(long long *tree, long long x) {
long long sum = 0;
for (; x; x -= (x & -x)) sum += tree[x];
return sum;
}
void add(long long *tree, long long x, long long y) {
for (; x <= n; x += (x & -x)) tree[x] += y;
}
int main() {
n = read(), q = read();
for (long long i = 1; i <= n; i++) a[i] = a[i - 1] + read();
while (q--) {
char c;
cin >> c;
if (c == 'C') {
long long l = read(), r = read(), x = read();
add(tree1, l, x);
add(tree1, r + 1, -x);
add(tree2, l, l * x);
add(tree2, r + 1, -(r + 1) * x);
}
else {
long long l = read(), r = read(), ans = 0;
ans = (a[r] + (r + 1) * ask(tree1, r) - ask(tree2, r)) - (a[l - 1] + l * ask(tree1, l - 1) - ask(tree2, l - 1));
printf("%lld\n", ans);
}
}
}