注意:
lazy标记可以重叠,所以每次是lazy标记+x,而不是=x。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
LL tree[maxn<<2]={0},lazy[maxn<<2]={0};
void Pushup(int rt){
tree[rt] = tree[rt<<1]+tree[rt<<1|1];
}
void Build(int rt,int l,int r){
lazy[rt] = 0;
if(l==r){
scanf("%lld",&tree[rt]);
return ;
}
int mid = (l+r)>>1;
Build(rt<<1,l,mid);
Build(rt<<1|1,mid+1,r);
Pushup(rt);
}
void Pushdown(int rt,int ln,int rn){
if(lazy[rt]!=0){
lazy[rt<<1] += lazy[rt];//
lazy[rt<<1|1] += lazy[rt];//
tree[rt<<1] += lazy[rt]*ln;//
tree[rt<<1|1] += lazy[rt]*rn;//
lazy[rt] = 0;
}
}
void Update(int L,int R,LL x,int rt,int l,int r){
if(L<=l&&r<=R){
tree[rt] += x*(r-l+1);//
lazy[rt] += x;//
return ;
}
int mid = (l+r)>>1;
Pushdown(rt,mid-l+1,r-mid);//
if(L<=mid) Update(L,R,x,rt<<1,l,mid);
if(R>mid) Update(L,R,x,rt<<1|1,mid+1,r);
Pushup(rt);
}
LL Query(int L,int R,int rt,int l,int r){
if(L<=l&&r<=R){
return tree[rt];
}
int mid = (l+r)>>1;
LL ans = 0;
Pushdown(rt,mid-l+1,r-mid);//
if(L<=mid) ans += Query(L,R,rt<<1,l,mid);
if(R>mid) ans += Query(L,R,rt<<1|1,mid+1,r);
return ans;
}
int main(void){
int n,q;scanf("%d%d",&n,&q);
Build(1,1,n);
for(int i=1;i<=q;i++){
char ss[5];scanf("%s",ss);
if(ss[0]=='Q'){
int l,r;scanf("%d%d",&l,&r);
printf("%lld\n",Query(l,r,1,1,n));
}else{
int l,r;LL x;scanf("%d%d%lld",&l,&r,&x);
Update(l,r,x,1,1,n);
}
}
return 0;
}