//正常思路,线段树模版
#include<stdio.h>
#define N 111111
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
long long int add[N<<2];
long long int sum[N<<2];
void pushup(int rt)
{
sum[rt]=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]+=(m-(m>>1))*add[rt];
sum[rt<<1|1]+=(m>>1)*add[rt];
add[rt]=0;
}
}
void build(int l,int r,int rt)
{
int m;
add[rt]=0;
if(l==r)
{
scanf("%lld",&sum[rt]);
return ;
}
m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int L,int R,int c,int l,int r,int rt)
{
int m;
if(L<=l&&R>=r)
{
add[rt]+=c;
sum[rt]+=c*(r-l+1);
return ;
}
pushdown(rt,r-l+1);
m=(l+r)>>1;
if(L<=m)
update(L,R,c,lson);
if(R>m)
update(L,R,c,rson);
pushup(rt);
}
long long int query(int L,int R,int l,int r,int rt)
{
long long int m, ret=0;
if(L<=l&&R>=r)
return sum[rt];
pushdown(rt,r-l+1);
m=(l+r)>>1;
if(L<=m)
ret+=query(L,R,lson);
if(R>m)
ret+=query(L,R,rson);
return ret;
}
int main()
{
int m,n;
scanf("%d%d",&n,&m);
build(1,n,1);
while(m--)
{
char s[5];
int a,b,c;
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d%d",&a,&b);
printf("%lld\n",query(a,b,1,n,1));
}
else
{
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1,n,1);
}
}
return 0;
}
下面是另一种思路
线段树维护的是以下2个数据
*给这个节点对应的区间内的所有元素共同加的值(如果只有一部分区间,就执行b)
*在这个节点的对应区间中除去a中之外其它值的和
#include<stdio.h>
#define MN 111111
int N,Q;
char T[6];
long long int data[MN<<2],datb[MN<<2];
int min(int x,int y)
{
return x>y?y:x;
}
int max(int x,int y)
{
return x>y?x:y;
}
void add(int a,int b,int x,int k,int l,int r)
{
if(a<=l&&r<=b)
data[k]+=x;
else
if(l<b&&a<r)
{
datb[k]+=(min(b,r)-max(a,l))*x;
add(a,b,x,k*2+1,l,(l+r)/2);
add(a,b,x,k*2+2,(l+r)/2,r);
}
}
long long int sum(int a,int b,int k,int l,int r)
{
long long int res=0;
if(b<=l||r<=a)
return 0;
else
if(a<=l&&r<=b)
return data[k]*(r-l)+datb[k];
else
{
res=(min(b,r)-max(a,l))*data[k];
res+=sum(a,b,k*2+1,l,(l+r)/2);
res+=sum(a,b,k*2+2,(l+r)/2,r);
return res;
}
}
int main(void)
{
int i,a,b,c;
scanf("%d%d",&N,&Q);
for(i=0;i<N;i++)
{
scanf("%d",&a);
add(i,i+1,a,0,0,N);
}
for(i=0;i<Q;i++)
{
scanf("%s",T);
if(T[0]=='C')
{
scanf("%d%d%d",&a,&b,&c);
add(a-1,b,c,0,0,N);
}
else
{
scanf("%d%d",&a,&b);
printf("%lld\n",sum(a-1,b,0,0,N));
}
}
}