题解:模板题,放一个lazy标志
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
int const N = 100000 + 10;
ll n,q;
struct Node
{
ll l,r;
ll sum,lazy;
void updata(ll val){
sum += (r-l+1)*val;
lazy += val;
}
}node[N<<2];
void push_up(ll id){
node[id].sum = node[id<<1].sum + node[id<<1|1].sum;
}
void push_down(ll id){
ll lazy =node[id].lazy;
if(lazy){
node[id<<1].updata(lazy);
node[id<<1|1].updata(lazy);
node[id].lazy = 0;
}
}
void build(ll id,ll l,ll r){
node[id].l = l,node[id].r = r;
node[id].lazy = 0;
if(l == r) scanf("%lld",&node[id].sum);
else{
ll mid = (l + r) >> 1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
push_up(id);
}
}
ll query(ll id,ll L,ll R){//求[l,r]区间所有结点的和
ll l = node[id].l,r = node[id].r;
if(L <= l && r <= R) //直接得到区间的结果,不用lazy往下更新
return node[id].sum;
else{
push_down(id);
ll mid = (l + r) >> 1;
ll res = 0;
if(L <= mid) res += query(id<<1,L,R);
if(mid < R) res += query(id<<1|1,L,R);
push_up(id);
return res;
}
}
void updata(ll id,ll L,ll R,ll k){ //将[l,r]区间的每个数加上k
ll l = node[id].l, r = node[id].r;
if(L <= l && r <= R){
node[id].updata(k);
}else{
ll mid = (l + r) >> 1;
push_down(id);
if(L <= mid) updata(id<<1,L,R,k);
if(mid < R) updata(id<<1|1,L,R,k);
push_up(id);
}
}
int main(){
scanf("%lld%lld",&n,&q);
build(1,1,n);
char t;
ll x,y,z;
for(ll i=1;i<=q;i++){
scanf(" %c",&t);
if(t == 'Q'){
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(1,x,y));
}else{
scanf("%lld%lld%lld",&x,&y,&z);
updata(1,x,y,z);
}
}
return 0;
}