应用:数组大批量相同重复操作。
#include<iostream>
#include<vector>
using namespace std;
const int MAXN=100005;
long long tree_sum[MAXN*4];
long long lazy_tag[MAXN*4];
long long arr[MAXN];
void push_up(int p){
tree_sum[p]=tree_sum[p*2]+tree_sum[p*2+1];
}
void push_down(int p,int l,int r){
if(lazy_tag[p]!=0){
int mid=(l+r)/2;
lazy_tag[p*2]+=lazy_tag[p];
tree_sum[p*2]+=lazy_tag[p]*(mid-l+1);
lazy_tag[p*2+1]+=lazy_tag[p];
tree_sum[p*2+1]+=lazy_tag[p]*(r-mid);
lazy_tag[p]=0;
}
}
void build_tree(int p,int l,int r){
lazy_tag[p]=0;
if(l==r){
tree_sum[p]=arr[l];
return;
}
int mid=(l+r)/2;
build_tree(p*2,l,mid);
build_tree(p*2+1,mid+1,r);
push_up(p);
}
void update_tree(int p,int l,int r,int ql,int qr,long long val){
if(ql<=l&&r<=qr){
tree_sum[p]+=val*(r-l+1);
lazy_tag[p]+=val;
return;
}
push_down(p,l,r);
int mid=(l+r)/2;
if(ql<=mid)update_tree(p*2,l,mid,ql,qr,val);
if(qr>mid)update_tree(p*2+1,mid+1,r,ql,qr,val);
push_up(p);
}
long long query_tree(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){
return tree_sum[p];
}
push_down(p,l,r);
int mid=(l+r)/2;
long long total_sum=0;
if(ql<=mid)total_sum+=query_tree(p*2,l,mid,ql,qr);
if(qr>mid)total_sum+=query_tree(p*2+1,mid+1,r,ql,qr);
return total_sum;
}
int main(){
int n=5;
for(int i=1;i<n;i++){
arr[i]=i;
}
build_tree(1,1,n);
cout<<"区间[2,4]的初试和:"<<query_tree(1,1,n,2,4)<<endl;
update_tree(1,1,n,2,4,10);
cout<<"区间【2,4】修改后的和"<<query_tree(1,1, n,2,4)<<endl;
return 0;
}
要点解析:arr数组初始化后就被抛弃,所以每次修改并没有修改到底层。
同时,每次线段树是以区间为最小单位进行操作,并且每次操作只修改一层,清除本层的lazy_val后就推给下一层不管。只要区间符合条件就直接向上层汇报结果,不向下细分了。怎么说呢有点只可意会不可言传的味道。