指定区间,对区间里的每个数进行统一的操作(加和),这里用到延迟数组标记。
树状数组线段树建树,每个节点表示该节点所在区间的和。
add [ ]数组用来标记当前节点所延迟的向下加和的数。
PushDown() 向下更新。
#include<stdio.h>
#define maxn 110000
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define LL long long
int n, cas;
LL add[maxn<<2];
LL sum[maxn<<2];
LL operate(LL a, LL b){
return a+b;
}
void PushUp(int rt){
sum[rt] = operate(sum[rt<<1], sum[rt<<1|1]);
}
void PushDown(int rt, int m){
if(add[rt]){
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += add[rt]*(m-(m>>1));
sum[rt<<1|1] += add[rt]*(m>>1);
add[rt] = 0;
}
}
void build(int l, int r, int rt){
add[rt] = 0;
if(l == r){
scanf("%lld", &sum[rt]);
return;
}
int m = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void Update(int L, int R, int c, int l, int r, int rt){
if(L<=l && r<=R){
add[rt] += c;
sum[rt] += (LL)c * (r-l+1);
return ;
}
PushDown(rt, r-l+1);
int m = (l+r)>>1;
if(L<=m) Update(L, R, c, lson);
if(R>m) Update(L, R, c, rson);
PushUp(rt);
}
LL Query(int L, int R, int l, int r, int rt){
if(L<=l && r<=R){
return sum[rt];
}
PushDown(rt, r-l+1);
int m = (l+r)>>1;
LL ret = 0;
if(L<=m) ret += Query(L, R, lson);
if(R>m) ret += Query(L, R, rson);
return ret;
}
int main(){
int a, b, c;
char ch[2];
//freopen("in.txt", "r", stdin);
while(scanf("%d %d", &n, &cas) != EOF){
build(1, n, 1);
while(cas--){
scanf("%s", ch);
if(ch[0] == 'Q'){
scanf("%d %d", &a, &b);
printf("%lld\n", Query(a, b, 1, n, 1));
}else if(ch[0] == 'C'){
scanf("%d %d %d", &a, &b, &c);
Update(a, b, c, 1, n, 1);
}
}
}
return 0;
}