这种线段树支持区间修改和区间查询,区间修改的操作通过懒惰标记(lazy tag)实现。
一道支持区间修改和区间查询的线段树的模板题:Luogu P3372 【模板】线段树 1。下面附上AC代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=400010;
struct Node{
int l,r,ls,rs;
long long c,s;
}T[MAXN];
int cnt=0,x[MAXN];
int build(int l,int r){
int t=cnt++;
T[t]=(Node){l,r,-1,-1,0ll,0ll};
if(l<r){
int mid=(l+r)>>1;
T[t].ls=build(l,mid);
T[t].rs=build(mid+1,r);
T[t].s=T[T[t].ls].s+T[T[t].rs].s;
}
else T[t].s=x[l];
return t;
}
void pushdown(int v){
if(T[v].c){
if(T[v].l<T[v].r){
T[T[v].ls].c+=T[v].c;
T[T[v].ls].s+=(T[T[v].ls].r-T[T[v].ls].l+1)*T[v].c;
T[T[v].rs].c+=T[v].c;
T[T[v].rs].s+=(T[T[v].rs].r-T[T[v].rs].l+1)*T[v].c;
}
T[v].c=0;
}
}
void change(int v,int l,int r,int c){
pushdown(v);
if(l<=T[v].l && T[v].r<=r){
T[v].c+=c;
T[v].s+=(T[v].r-T[v].l+1)*c;
return;
}
if(l>T[v].r || r<T[v].l) return;
change(T[v].ls,l,r,c);
change(T[v].rs,l,r,c);
T[v].s=T[T[v].ls].s+T[T[v].rs].s;
}
long long query(int v,int l,int r){
if(l<=T[v].l && T[v].r<=r) return T[v].s;
if(l>T[v].r || T[v].l>r) return 0;
pushdown(v);
return query(T[v].ls,l,r)+query(T[v].rs,l,r);
}
int main(){
int N, M;
scanf("%d%d",&N, &M);
for(int i=0;i<N;i++) scanf("%d",&x[i]);
int root=build(0,N-1);
while(M--){
int t; scanf("%d",&t);
if(t==1){
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
change(root,l-1,r-1,c);
}
else{
int l,r; scanf("%d%d",&l,&r);
printf("%lld\n",query(root,l-1,r-1));
}
}
return 0;
}
网友评论