Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 109152 | Accepted: 33998 | |
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
给一个含有 N 个元素的数组,再给 M 个操作。其中 M 个操作为求区间和或者区间元素统一加上一个数。
对于区间和询问操作,用树状数组维护每个元素的前缀和,用前缀和之差来表示区间和。
对于区间修改操作,有
i<l : s'(i) = s(i)
l <= i <= r : s'(i) = s(i) + x*(i-l-1) = s(i) + x*i - x*(l-1)
I>r : s'(i) = s(i) + x*(r-l-1) = s(i) + x*r - x*(l-1)
这时对区间的修改只需要对区间两端点操作就可以了,需要维护两个树状数组:
一个保存原数组,区间首的 -x(l-1) 和区间尾的 x*r, 这两项是与 i 无关的常数项
一个保存区间首的 x 和区间尾的 -x,这两项是与 i 有关的
具体分析见《挑战程序设计竞赛》181页。
树状数组的基本原理见《挑战程序设计竞赛》174页。
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
const int maxn = 100000 + 10;
LL Bit[maxn];//第一个树状数组
LL Bit1[maxn];//第二个树状数组
int N, M;
char C;
//单点更改
void Add(LL *B, int p, int x)
{
while(p <= N)
{
B[p] += x;
p += p&-p;
}
}
//求前缀和
LL Sum(LL *B, int p)
{
LL res = 0;
while(p)
{
res += B[p];
p -= p&-p;
}
return res;
}
int main ()
{
scanf("%d %d", &N, &M);
for(int i= 1; i<= N; i++)
{
LL temp;
scanf("%lld", &temp);
Add(Bit, i, temp);
}
for(int k= 0; k< M; k++)
{
scanf(" %c", &C);
if(C == 'C')
{
int l, r;
LL x;
scanf("%d %d %lld", &l, &r, &x);
//对区间首尾的四项操作
Add(Bit, l, -(l-1)*x);
Add(Bit1, l, x);
Add(Bit, r+1, x*r);
Add(Bit1, r+1, -x);
}
else
{
int l, r;
scanf("%d %d", &l, &r);
//分别求前缀和再作差
LL res = 0;
res += Sum(Bit, r) + Sum(Bit1, r) * r;
res -= Sum(Bit, l-1) + Sum(Bit1, l-1) * (l-1);
printf("%lld\n", res);
}
}
return 0;
}