应用情景
线段树在广义上被归类为二叉搜索树,适用于满足于区间加法的问题。
实现
节点结构
struct node{
int l,r;
long long val,lazy;
}tree[1000000];
通过数组进行建树
void build(int p,int l,int r){
tree[p].l=l;
tree[p].r=r;
tree[p].lazy=0;
if(l==r) {
tree[p].val = arr[l];
return;
}
int mid=(l+r)>>1;
build(2*p,l,mid);
build(2*p+1,mid+1,r);
tree[p].val=tree[2*p].val+tree[2*p+1].val;
}
对节点的lazy标记进行下传操作
//下传lazy标记
void spread(int p){
if(tree[p].lazy){
tree[2*p].val+=(tree[2*p].r-tree[2*p].l+1)*tree[p].lazy;
tree[2*p].lazy+=tree[p].lazy;
tree[2*p+1].val+=(tree[2*p+1].r-tree[2*p+1].l+1)*tree[p].lazy;
tree[2*p+1].lazy+=tree[p].lazy;
tree[p].lazy=0;
}
}
对区间进行修改
//区间修改
void change(int p,int l, int r,int x){
//如果覆盖,打上lazy标记
if(tree[p].l>=l && tree[p].r<=r){
tree[p].val+=x*(tree[p].r-tree[p].l+1);
tree[p].lazy+=x;
return;
}
spread(p);
int mid=(tree[p].l+tree[p].r)>>1;
if(mid<r)
change(2*p+1,l,r,x);
if(mid>=l)
change(2*p,l,r,x);
tree[p].val=tree[p*2].val+tree[p*2+1].val;
}
搜索区间和
long long search(int p,int l,int r){
if(tree[p].l>=l && tree[p].r<=r)
return tree[p].val;
long long ans=0;
spread(p);
int mid=(tree[p].l+tree[p].r)>>1;
if(mid<r)
ans+= search(2*p+1,l,r);
if(mid>=l)
ans+= search(p*2,l,r);
return ans;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
struct node{
int l,r;
long long val,lazy;
}tree[1000000];
int arr[1000000];
//建树操作
void build(int p,int l,int r){
tree[p].l=l;
tree[p].r=r;
tree[p].lazy=0;
if(l==r) {
tree[p].val = arr[l];
return;
}
int mid=(l+r)>>1;
build(2*p,l,mid);
build(2*p+1,mid+1,r);
tree[p].val=tree[2*p].val+tree[2*p+1].val;
}
//下传lazy标记
void spread(int p){
if(tree[p].lazy){
tree[2*p].val+=(tree[2*p].r-tree[2*p].l+1)*tree[p].lazy;
tree[2*p].lazy+=tree[p].lazy;
tree[2*p+1].val+=(tree[2*p+1].r-tree[2*p+1].l+1)*tree[p].lazy;
tree[2*p+1].lazy+=tree[p].lazy;
tree[p].lazy=0;
}
}
//区间修改
void change(int p,int l, int r,int x){
//如果覆盖,打上lazy标记
if(tree[p].l>=l && tree[p].r<=r){
tree[p].val+=x*(tree[p].r-tree[p].l+1);
tree[p].lazy+=x;
return;
}
spread(p);
int mid=(tree[p].l+tree[p].r)>>1;
if(mid<r)
change(2*p+1,l,r,x);
if(mid>=l)
change(2*p,l,r,x);
tree[p].val=tree[p*2].val+tree[p*2+1].val;
}
long long search(int p,int l,int r){
if(tree[p].l>=l && tree[p].r<=r)
return tree[p].val;
long long ans=0;
spread(p);
int mid=(tree[p].l+tree[p].r)>>1;
if(mid<r)
ans+= search(2*p+1,l,r);
if(mid>=l)
ans+= search(p*2,l,r);
return ans;
}
int main(){
int n,m;
cin >> n >>m;
for(int i=1;i<=n;i++)
cin >> arr[i];
build(1,1,n);
for(int i=1;i<=m;i++)
{
int q,x,y,z;
cin>>q;
if(q==1){
cin>>x>>y>> z;
change(1,x,y,z);
}
else {
cin>>x>>y;
cout<<search(1,x,y)<<endl;
}
}
return 0;
}