整理一下标准的线段树模板,区间更新,求区间和两种操作;
还是用数组的方法来表示线段树;
先是定义节点:
struct node{
long long sum,lazy;
}c[maxx<<2];
再是建树:(记得l==r时,c[u].sum=a[l],l和r表示的是线段的端点)
void build(int u,int l,int r){
c[u].lazy=0;
if(l==r) c[u].sum=a[l];
else{
int m=(l+r)/2;
build(2*u, l, m);
build(2*u+1, m+1, r);
c[u].sum=c[2*u].sum+c[2*u+1].sum;
}
}
然后是pushdown操作:(记得要最后把c[u]的lazy标记清空)
void pushdown(int u,int l,int r){
int m=(l+r)/2;
c[2*u].sum+=c[u].lazy*(m-l+1);
c[2*u].lazy+=c[u].lazy;
c[2*u+1].sum+=c[u].lazy*(r-m);
c[2*u+1].lazy+=c[u].lazy;
c[u].lazy=0;
}
然后是update操作:(sl和sr是当前节点的两端点,l和r是待更新的范围,注意前面两个if的范围,后面要先pushdown把lazy标传递下去才能分治去update,最后求出c[u].sum)
void update(int u,int sl,int sr,int l,int r,int k){
if(sl>r || sr<l) return ;
if(sl>=l && sr<=r){
c[u].lazy+=k;
c[u].sum+=k*(sr-sl+1);
return ;
}
int m=(sl+sr)/2;
pushdown(u, sl, sr);
update(2*u, sl, m, l, r, k);
update(2*u+1, m+1, sr, l, r, k);
c[u].sum=c[2*u].sum+c[2*u+1].sum;
return ;
}
最后是query操作,其实和update操作差不多:(后面记得要先把lazy标签pushdown下去,才能询问儿子节点)
long long query(int u,int sl,int sr,int l,int r){
if(sl>r || sr<l) return 0;
if(sl>=l && sr<=r) return c[u].sum;
pushdown(u, sl, sr);
int m=(sl+sr)/2;
return query(2*u, sl, m, l, r)+query(2*u+1, m+1, sr, l, r);
}
主函数(codevs1082):
int main(){
std::ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
cin>>m;
int com,x,y,k;
while(m--){
cin>>com;
if(com==1){
cin>>x>>y>>k;
update(1,1,n,x,y,k);
}
else if(com==2){
cin>>x>>y;
cout<<query(1,1,n,x,y)<<endl;
}
}
}