利用懒惰标记使更新延迟到下一次需要更新or询问时。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
using namespace std;
#define ms(X) memset(X,0,sizeof(X));
typedef long long ll;
ll tree[120005<<2],cnt[120005<<2];/*感觉cnt是int也可以啊,因为最大是10000*100000,不会爆int啊,然而wa了......*/
int N,Q;
void build(int tn,int l,int r)
{
if(l==r) {scanf("%lld",tree+tn);return;}
int mid=(l+r)>>1;
build(tn<<1,l,mid);
build(tn<<1|1,mid+1,r);
tree[tn]=tree[tn<<1]+tree[tn<<1|1];
}
void pushdown(int tn,int m)
{
if(cnt[tn]&&m>1)
{
cnt[tn<<1]+=cnt[tn];
cnt[tn<<1|1]+=cnt[tn];
tree[tn<<1]+=(m-(m>>1))*cnt[tn];
tree[tn<<1|1]+=(m>>1)*cnt[tn];
cnt[tn]=0;
}
}
void chang(int tn,int l,int r,int a,int b,int c)
{
if(a<=l&&r<=b){
cnt[tn]+=c;
tree[tn]+=(ll)c*(r-l+1);
return;
}
pushdown(tn,r-l+1);
int mid=(l+r)>>1;
if(b<=mid) chang(tn<<1,l,mid,a,b,c);
else if(a>mid) chang(tn<<1|1,mid+1,r,a,b,c);
else{
chang(tn<<1,l,mid,a,mid,c);
chang(tn<<1|1,mid+1,r,mid+1,b,c);
}
tree[tn]=tree[tn<<1]+tree[tn<<1|1];
}
ll query(int tn,int l,int r,int a,int b)
{
if(a<=l&&r<=b) return tree[tn];
pushdown(tn,r-l+1);
int mid=(l+r)>>1;
if(b<=mid) return query(tn<<1,l,mid,a,b);
else if(a>mid) return query(tn<<1|1,mid+1,r,a,b);
else return query(tn<<1,l,mid,a,mid)+query(tn<<1|1,mid+1,r,mid+1,b);
}
int main(int argc, char const *argv[])
{
while(cin>>N>>Q)
{
ms(cnt);
build(1,1,N);
char ss[3];
while(Q--){scanf("%s",ss);
if(ss[0]=='C'){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
chang(1,1,N,a,b,c);
}
else {
int a,b;
scanf("%d %d",&a,&b);
printf("%lld\n",query(1,1,N,a,b));
}}
}
return 0;
}