做法:一开始做的成段更新,有学会了成段更新的一下必要规则
#include <iostream>
#include <cstdio>
#include <cstring>
#define left l,m,x<<1
#define right m+1,r,x<<1|1
#define LL long long
#define LMT 100004
//成段更新原则:一定要有表现出每一次改变的所有影响
//在看题的一开始就要确定使用数值的类型
using namespace std;
LL add[LMT<<2],sum[LMT<<2];
void build(int l,int r,int x)
{
if(l==r)
{
scanf("%I64d",&sum[x]);
return;
}
int m=(l+r)>>1;
build(left);
build(right);
sum[x]=sum[x<<1]+sum[x<<1|1];
}
void cut(int x,int have)
{
if(add[x])
{
add[x<<1]+=add[x];
add[x<<1|1]+=add[x];
sum[x<<1]+=add[x]*(have-(have>>1));//把add 的影响直接体现出来,方便体现影响
sum[x<<1|1]+=add[x]*(have>>1);
add[x]=0;
}
}
void update(LL key,int L,int R,int l,int r,int x)
{
if(L<=l&&r<=R)
{
add[x]+=key;
sum[x]+=(r-l+1)*key;
return;
}
int m=(l+r)>>1;
cut(x,r-l+1);
if(L<=m)update(key,L,R,left);
if(R>m)update(key,L,R,right);
sum[x]=sum[x<<1]+sum[x<<1|1];
}
LL query(int L,int R,int l,int r,int x)
{
if(L<=l&&r<=R)return sum[x];
int m=(l+r)>>1;
LL ret=0;
cut(x,r-l+1);
if(L<=m)ret+=query(L,R,left);
if(R>m)ret+=query(L,R,right);
return ret;
}
int main()
{
int n,q,a,b;
LL k;
char ord[3];
while(~scanf("%d%d",&n,&q))
{
memset(add,0,sizeof(add));
build(1,n,1);
while(q--)
{
scanf("%s",ord);
if(strcmp(ord,"Q")==0)
{
scanf("%d%d",&a,&b);
printf("%I64d\n",query(a,b,1,n,1));
}
else
{
scanf("%d%d%I64d",&a,&b,&k);
update(k,a,b,1,n,1);
}
}
}
return 0;
}