线段树模板区间加(含懒标记)

发布时间 2023-12-09 22:00:59作者: potential-star
const int N = 1e5 + 10;
int n, m;
int a[N];
struct Tree{
	int l,r;
	ll sum,add;
	
}tr[4*N];
void build(int u,int l,int r){
	// l=tr[u].l;r=tr[u].r;
	//注释掉的部分是典型的错误,对于build过程中我们是初始化编号对应区间节点,上面赋值逻辑反了
	tr[u]={l,r};
	if(l==r)tr[u].sum=a[l];
	else{
		int mid=l+r>>1;
		build(u<<1,l,mid),build(u<<1|1,mid+1,r);
		tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
		
	}
}
void pushdown(int u){
	auto &root=tr[u],&b=tr[u<<1],&c=tr[u<<1|1];
	if(root.add){
		b.add+=root.add;b.sum+=(ll)(b.r-b.l+1)*root.add;
		c.add+=root.add;c.sum+=(ll)(c.r-c.l+1)*root.add;
		root.add=0;
	}
	
}

void update(int u,int x,int y,ll d){
	int l=tr[u].l, r=tr[u].r,mid=l+r>>1;
	if(x<=l&&y>=r){
		tr[u].sum+=(ll)(r-l+1)*d;
		tr[u].add+=d;
	}
	else {
		pushdown(u);
		if(x<=mid)update(u<<1,x,y,d);
		if(y>mid)update(u<<1|1,x,y,d);
		tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
	}
}
ll query(int u,int x,int y){
	int l=tr[u].l,r=tr[u].r,mid=l+r>>1;
	if(x<=l&&y>=r)return tr[u].sum;
	else {
		pushdown(u);
		ll ans=0;
		if(x<=mid)ans+=query(u<<1,x,y);
		if(y>mid)ans+=query(u<<1|1,x,y);
		return ans;
	}
	
}
void solve(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	build(1,1,n);
	while(m--){
	int op;cin>>op;
		if(op==1){
			int l,r,d;
			cin>>l>>r>>d;
			update(1,l,r,d);
		}
		else {
			int l,r;
			cin>>l>>r;
			ll ans=query(1,l,r);
			cout<<ans<<endl;
		}
	}
}