♻️lzhh_lzhh32 • 1个月前
/*
线段树:叶子节点就是数组
父节点(i)为子节点(2*i,2*i+1)汇总信息
*/
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct TreeNode{
int l,r;
long long val;
long long lazy; //子节点待标记的值
}tree[400005]; //习惯上长度皆为n*4
long long d[100005]; //初始数组
void maketree(int node,int l,int r){ //递归建区间l,r之间的树
tree[node].l=l;
tree[node].r=r;
if(l==r){ //叶节点
tree[node].val=d[l];
}else{
int mid=(l+r)/2;
maketree(node*2,l,mid); //建左子树
maketree(node*2+1,mid+1,r); //建右子树
tree[node].val+=tree[node*2].val+tree[node*2+1].val; //汇总父节点
}
}
void pushdown(int node){ //把k往下推
if(tree[node].lazy){
tree[node*2].val+=(tree[node*2].r-tree[node*2].l+1)*tree[node].lazy;
tree[node*2+1].val+=(tree[node*2+1].r-tree[node*2+1].l+1)*tree[node].lazy;
tree[node*2].lazy+=tree[node].lazy; //子节点也可能有子节点,不能丢掉待更新信息
tree[node*2+1].lazy+=tree[node].lazy;
tree[node].lazy=0;
}
}
//下面的所有函数,l r代表总区间,x y代表操作区间
void addk(int node,int l,int r,int x,int y,int k){
if(x<=l&&r<=y){ //[x,y]包含[l,r]
tree[node].val+=(r-l+1)*k;
tree[node].lazy+=k;
}
else if(y<l||r<x) return; //[x,y]在[l,r]之外,不更新
else{ //半包含
int mid=(l+r)/2;
pushdown(node);
addk(node*2,l,mid,x,y,k);
addk(node*2+1,mid+1,r,x,y,k); //一直拆到前两种情况出现
tree[node].val=tree[node*2].val+tree[node*2+1].val;
}
}
long long getsum(int node,int l,int r,int x,int y){
if(x<=l&&r<=y) return tree[node].val; //[x,y]包含[l,r]
else if(y<l||r<x) return 0; //[x,y]在[l,r]之外,不更新
else{ //半包含
int mid=(l+r)/2;
pushdown(node);
return getsum(node*2,l,mid,x,y)+getsum(node*2+1,mid+1,r,x,y); //同理,拆下去
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>d[i];
maketree(1,1,n); //朴实无华先把树建好
while(m--){
int op,x,y,k;
cin>>op;
if(op==1){
cin>>x>>y>>k;
addk(1,1,n,x,y,k);
}
if(op==2){
cin>>x>>y;
cout<<getsum(1,1,n,x,y)<<endl;
}
}
return 0;
}
评论:
请先登录,才能进行评论