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:P200.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int maxn = 100000+7;
int n, q, a[maxn];
ll sum[maxn], c[2][maxn];
ll ans = 0;
int lowbit(int x){
return x & -x;
}
ll ask(int k, int x){
ll sum = 0;
while(x){
sum += c[k][x];
x -= lowbit(x);
}
return sum;
}
void add(int k, int x, int y){
while(x <= n){
c[k][x] += y;
x += lowbit(x);
}
}
int main()
{
scanf("%d %d", &n, &q);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
int l, r, w;
while(q--){
char ch[2];
scanf("%s", ch);
if(ch[0] == 'Q'){
ans = 0;
scanf("%d %d", &l, &r);
ans += (sum[r] + (r+1)*ask(0, r) - ask(1, r));
ans -= (sum[l-1] + l*ask(0, l-1) - ask(1, l-1));
printf("%lld\n", ans);
}else{
scanf("%d %d %d", &l, &r, &w);
add(0, l, w);
add(0, r+1, -w);
add(1, l, l*w);
add(1, r+1, -(r+1)*w);
}
}
return 0;
}
方法2:线段树+延迟标记,P210
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF -0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 100010;
int n, m;
int a[maxn];
struct SegmentTree{
int l, r;
ll sum, add;
#define l(x) t[x].l
#define r(x) t[x].r
#define sum(x) t[x].sum
#define add(x) t[x].add
}t[maxn<<2];
void push_up(int p){
sum(p) = sum(2*p) + sum(2*p+1);
}
void build(int p, int l, int r){
l(p) = l, r(p) = r;
if(l == r){
sum(p) = a[l];
return ;
}
int mid = (l+r)/2;
build(2*p, l, mid);
build(2*p+1, mid+1, r);
push_up(p);
}
void push_down(int p){
if(add(p)){//节点p有标记
sum(2*p) += add(p)*(r(2*p)-l(2*p)+1);//更新左子节点信息
sum(2*p+1) += add(p)*(r(2*p+1)-l(2*p+1)+1);//更新右子节点信息
add(2*p) += add(p);//给左子节点打延迟标记
add(2*p+1) += add(p);//给右子节点打延迟标记
add(p) = 0;//清除p的标记
}
}
void change(int p, int l, int r, int d){
if(l <= l(p) && r >= r(p)){//完全覆盖
sum(p) += d*(r(p)-l(p)+1);//更新节点信息
add(p) += d;//给节点打延迟标记
return ;
}
push_down(p);//下传延迟标记
int mid = (l(p)+r(p)) / 2;
if(l <= mid) change(2*p, l, r, d);
if(r > mid) change(2*p+1, l, r, d);
push_up(p);
}
ll ask(int p, int l, int r){
if(l <= l(p) && r >= r(p)){
return sum(p);
}
push_down(p);//下传延迟标记
int mid = (l(p)+r(p)) / 2;
ll ans = 0;
if(l <= mid) ans += ask(2*p, l, r);
if(r > mid) ans += ask(2*p+1, l, r);
return ans;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
build(1,1,n);
while(m--){
char op[2];
int l, r, d;
scanf("%s%d%d", op, &l, &r);
if(op[0]=='C'){
scanf("%d", &d);
change(1,l,r,d);
}else{
ll ans = ask(1, l, r);
printf("%lld\n", ans);
}
}
return 0;
}
3、分块,P215
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 100010;
int n, m, t;
ll sum[maxn], a[maxn], add[maxn];
ll L[maxn], R[maxn];
int pos[maxn];
void change(int l, int r, ll v){
int p = pos[l], q = pos[r];
if(p == q){
for(int i = l; i <= r; i++) a[i] += v;
sum[p] += (r-l+1)*v;
}else{
for(int i = p+1; i <= q-1; i++)
add[i] += v;
for(int i = l; i <= R[p]; i++)
a[i] += v;
sum[p] += (R[p]-l+1)*v;
for(int i = L[q]; i <= r; i++)
a[i] += v;
sum[q] += (r-L[q]+1)*v;
}
}
ll ask(int l, int r){
ll ans = 0;
int p = pos[l], q = pos[r];
if(p == q){
for(int i = l; i <= r; i++)
ans += a[i];
ans += add[p]*(r-l+1);
}else{
for(int i = p+1; i <= q-1; i++)
ans += sum[i] + add[i]*(R[i]-L[i]+1);
for(int i = l; i <= R[p]; i++)
ans += a[i];
ans += add[p]*(R[p]-l+1);
for(int i = L[q]; i <= r; i++)
ans += a[i];
ans += add[q]*(r-L[q]+1);
}
return ans;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
}
t = int(sqrt(n*1.0));
for(int i = 1; i <= t; i++){
L[i] = int((i-1)*sqrt(n*1.0)) + 1;
R[i] = int(i*sqrt(n*1.0));
}
if(R[t] < n){
t++, L[t] = R[t-1] + 1;
R[t] = n;
}
for(int i = 1; i <= t; i++){
for(int j = L[i]; j <= R[i]; j++){
pos[j] = i;
sum[i] += a[j];
}
}
while(m--){
char op[2];
int l, r;
ll d;
scanf("%s %d %d", op, &l, &r);
if(op[0] == 'C'){
scanf("%lld", &d);
change(l, r, d);
}else{
printf("%lld\n", ask(l, r));
}
}
return 0;
}