sum[manx<<2]代表建立的线段树,区间和。
add[maxn<<2]为区间更新的懒惰标记。
A[maxn]为原数据
代码:
//PushUp函数更新节点信息
void PushUp(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
};
//建树
void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt]=A[l];
return ;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
PushUp(rt);
}
//点更新
void PointUpdate(int L,int C,int l,int r,int rt)
{
if(L==l&&L==r)
{
sum[rt]+=C;
return ;
}
int m=(l+r)>>1;
if(L<=m)
PointUpdate(L,C,l,m,rt<<1);
else
PointUpdate(L,C,m+1,r,rt<<1|1);
PushUp(rt);
}
//区间修改
void Update(int L,int R,int C,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
sum[rt]+=C*(r-l+1);
Add[rt]+=C;
return 0;
}
int m=(L+r)>>1;
PushDown(rt,m-l+1,r-m);
if(L<=m)
Update(L,R,C,l,m,rt<<1);
if(R>m)
Update(L,R,C,m+1,r,rt<<1|1);
PushUp(rt);
}
//下推标记
void PushDown(int rt,int ln,int rn)
{
if(Add[rt])
{
Add[rt<<1]+=Add[rt];
Add[rt<<1|1]+=Add[rt];
sum[rt<<1]+=ln*Add[rt];
sum[rt<<1|1]+=rn*Add[rt];
Add[rt]=0;
}
}
//区间查询
int query(int L,int R,int l,int r,int rt)
{
if(l>=L&&r<=R)
{
return sum[rt];
}
int m=(l+r)>>1;
PushDown(rt,m-l+1,r-m);
int ans=0;
if(L<=m)
ans+=query(L,R,l,m,rt<<1);
if(R>m)
ans+=query(L,R,m+1,r,rt<<1|1);
return ans;
}
//函数调用
//建树
Build(1,n,1);
//点修改
PointUpdate(L,C,1,n,1);
//区间修改
Update(L,R,C,1,n,1);
//区间查询
int ANS=query(L,R,1,n,1);