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 abc" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q ab" 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个整数和q个操作,有两种操作,C l r x表示把[l, r]中所有数都加x,Q l r表示输出[l, r]中数值的和。
用线段树和树状数组都能做。
方法一:线段树。因为操作一需要修改一个区间内所有的值,所以最坏情况下需要修改整个线段树,复杂度太高。所以可以用线段树来维护两个值,一个是区间共同加上的值,一个是除了这些共同值以外其他的值的和。
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <limits>
#include <new>
#include <utility>
#include <iterator>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long ll;
const int maxn = (1 << 18) - 1;
int n, q;
//data维护区间共同值,datb维护除了这些共同值以外的值的和
ll data[maxn], datb[maxn];
//对区间[a, b)同时加x
//k是节点的编号,对应的区间是[l, r)
void add(int a, int b, int x, int k, int l, int r)
{
if (a <= l && b >= r)
data[k] += x;
else
if (b > l && a < r)
{
datb[k] += (min(b, r) - max(a, l)) * x;
add(a, b, x, k*2+1, l, (l+r)/2);
add(a, b, x, k*2+2, (l+r)/2, r);
}
}
//计算[a, b)的和
//k是节点的编号,对应的区间是[l, r)
ll sum(int a, int b, int k, int l, int r)
{
if (b <= l || a >= r)
return 0;
if (a <= l && b >= r)
return (r - l) * data[k] + datb[k];
ll res = (min(b, r) - max(a, l)) * data[k];
res += sum(a, b, k*2+1, l, (l+r)/2);
res += sum(a, b, k*2+2, (l+r)/2, r);
return res;
}
int main()
{
cin >> n >> q;
for (int i = 0; i < n; ++i)
{
int num;
scanf("%d", &num);
add(i, i+1, num, 0, 0, n);
}
while (q--)
{
char s[5];
int l, r, x;
scanf("%s", s);
if (s[0] == 'C')
{
scanf("%d%d%d", &l, &r, &x);
add(l-1, r, x, 0, 0, n);
}
else
{
scanf("%d%d", &l, &r);
printf("%lld
", sum(l-1, r, 0, 0, n));
}
}
return 0;
}
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <limits>
#include <new>
#include <utility>
#include <iterator>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long ll;
const int maxn = 100010;
int n, q;
//BIT
ll bit0[maxn], bit1[maxn];
ll sum(ll* b, int i)
{
ll s = 0;
while (i > 0)
{
s += b[i];
i &= i - 1;
}
return s;
}
void add(ll* b, int i, int x)
{
while (i <= n)
{
b[i] += x;
i += i & (-i);
}
}
int main()
{
cin >> n >> q;
for (int i = 1; i <= n; ++i)
{
int num;
scanf("%d", &num);
add(bit0, i, num);
}
while (q--)
{
char s[5];
int l, r, x;
scanf("%s", s);
if (s[0] == 'C')
{
scanf("%d%d%d", &l, &r, &x);
add(bit0, l, -x*(l-1));
add(bit1, l, x);
add(bit0, r+1, x*r);
add(bit1, r+1, -x);
}
else
{
scanf("%d%d", &l, &r);
ll res = 0;
res += sum(bit0, r) + sum(bit1, r) * r;
res -= sum(bit0, l-1) + sum(bit1, l-1) * (l - 1);
printf("%lld
", res);
}
}
return 0;
}