基础的线段树区间修改和区间求和
贴代码吧
#include <stdio.h>
#define N 100010
struct Node
{
int l,r;
__int64 c,sum;//用c来存储在这个节点存储的增值,用sum来存储在该节点对应的区间上的和。
}p[3*N];
int que[N];
void build(int k,int s,int t)
{
int kl,kr,mid;
p[k].l=s;p[k].r=t;p[k].c=0;
p[k].sum=que[s];
if(s==t) return ;
mid=(s+t)>>1;kl=k<<1;kr=kl+1;
build(kl,s,mid);
build(kr,mid+1,t);
p[k].sum=p[kl].sum+p[kr].sum;
}
//关键操作,传递时,把之前根节点更新的增值加到子节点,同时把子节点上的sum也更新了
//然后把根节点的值设置为0,以免重复加到子节点
void trans(int k,int lk,int rk)
{
p[lk].c+=p[k].c;
p[rk].c+=p[k].c;
p[lk].sum+=p[k].c*(p[lk].r-p[lk].l+1);
p[rk].sum+=p[k].c*(p[rk].r-p[rk].l+1);
p[k].c=0;
}
void insert(int k,int s,int t,int v)
{
if(s<=p[k].l&&t>=p[k].r)
{
p[k].c+=v;
p[k].sum+=v*(p[k].r-p[k].l+1);
}
else {
int mid=(p[k].r+p[k].l)>>1,kl=k<<1,kr=kl+1;
if(p[k].c!=0)
trans(k,kl,kr);
if(s<=mid) insert(kl,s,t,v);
if(t>mid) insert(kr,s,t,v);
p[k].sum=p[kr].sum+p[kl].sum;
}
}
__int64 query(int k,int s,int t)
{
if(s<=p[k].l&&t>=p[k].r)
return p[k].sum;
int mid=(p[k].r+p[k].l)>>1,kl=k<<1,kr=kl+1;
if(p[k].c!=0)
trans(k,kl,kr);
__int64 a=0,b=0;
if(s<=mid) a=query(kl,s,t);
if(t>mid) b=query(kr,s,t);
return a+b;
}
int main()
{
char ch;
int i,n,m,a,b,t;
while(scanf("%d %d",&n,&m)!=EOF)
{
for(i=1;i<=n;++i) scanf("%d",que+i);
build(1,1,n);
while(m--)
{
getchar();
scanf("%c",&ch);
if(ch=='Q')
{
scanf("%d %d",&a,&b);
printf("%I64d\n",query(1,a,b));
}
else
{
scanf("%d %d %d",&a,&b,&t);
insert(1,a,b,t);
}
}
}
return 0;
}