一维数组
1.建树
void build(int l,int r,int o)//l,r表示当前节点区间,rt表示当前节点编号
{
if(l==r){//到叶节点,修改
cin>>a[o];
return ;
}
int mid=(l+r)>>1;//根据条件判断往左子树调用还是往右
build(l,mid,o<<1);
build(mid+1,r,o<<1|1);
a[o]=a[o<<1]+a[o<<1|1];//子节点更新了,所以本节点也需要更新信息
}
2.修改
(一)点修改:
void update(int L,int C,int l,int r,int o){//l,r表示当前节点区间,o表示当前节点编号
if(l==r){//到叶节点,修改
a[o]+=C;
return;
}
int m=(l+r)>>1;
//根据条件判断往左子树调用还是往右
if(L <= m) Update(L,C,l,m,o<<1);
else Update(L,C,m+1,r,o<<1|1);
a[o]=a[o<<1]+a[o<<1|1];//子节点更新了,所以本节点也需要更新信息
}
(二)区间修改:
void Update(int L,int R,int C,int l,int r,int o){//L,R表示操作区间,l,r表示当前节点区间,o表示当前节点编号
if(L <= l && r <= R){//如果本区间完全在操作区间[L,R]以内
a[o]+=C*(r-l+1);//更新数字和,向上保持正确
Add[o]+=C;//增加Add标记,表示本区间的Sum正确,子区间的Sum仍需要根据Add的值来调整
return ;
}
int m=(l+r)>>1;
PushDown(o,m-l+1,r-m);//下推标记
//这里判断左右子树跟[L,R]有无交集,有交集才递归
if(L <= m) update(L,R,C,l,m,o<<1);
if(R > m) update(L,R,C,m+1,r,o<<1|1);
a[o]=a[o<<1]+a[o<<1|1];//更新本节点信息
}
查询
询问A[L,R]的和
首先是下推标记的函数:
void PushDown(int rt,int ln,int rn){
//ln,rn为左子树,右子树的数字数量。
if(Add[rt]){
//下推标记
Add[rt<<1]+=Add[rt];
Add[rt<<1|1]+=Add[rt];
//修改子节点的Sum使之与对应的Add相对应
a[rt<<1]+=Add[rt]*ln;
a[rt<<1|1]+=Add[rt]*rn;
//清除本节点标记
Add[rt]=0;
}
}
区间查询
int Query(int L,int R,int l,int r,int rt){//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号
if(L <= l && r <= R){
//在区间内,直接返回
return Sum[rt];
}
int m=(l+r)>>1;
//下推标记,否则Sum可能不正确
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;
}