这样的线段树可以吗
查看原帖
这样的线段树可以吗
240374
hicode_002楼主2021/7/19 10:55
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
ll lazytag[400010],sumv[400010],a[400010];
inline void pushup(const int &o){
	sumv[o]=sumv[o<<1]+sumv[o<<1|1];
}
inline void build(const int &o,const int&l,const int&r){
	if(l==r){
		sumv[o]=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(o<<1,l,mid);
	build(o<<1|1,mid+1,r);
	pushup(o);
}
inline void change2(const int&o,const int&l,const int &r,const int &ql,const int&qr,const ll&k){
	if(l==ql&&r==qr){
		sumv[o]+=k*(qr-ql+1);
		lazytag[o]+=k;
		return ;
	}
	if(qr<ql)return ;
	if(ql<l||qr>r)return ;
	int mid=(l+r)>>1;
	if(ql<=mid&&qr<=mid){
		change2(o<<1,l,mid,ql,qr,k);
		sumv[o]+=(qr-ql+1)*k;
		return ;
	}
	if(qr>mid&&ql>mid){
		change2(o<<1|1,mid+1,r,ql,qr,k);
//		pushup(o);
		sumv[o]+=k*(qr-ql+1);
		return ;
	}
	if(ql<=mid&&qr>mid){
		change2(o<<1,l,mid,ql,mid,k);
		change2(o<<1|1,mid+1,r,mid+1,qr,k);
//		pushup(o);
		sumv[o]+=(qr-ql+1)*k;
		return ;
	}
}
inline ll querys(const int&o,const int&l,const int&r,const int&ql,const int&qr){
	if(l==ql&&r==qr){
		return sumv[o];
	}
	if(qr<ql)return 0;
	if(ql<l||qr>r)return 0;
	int mid=(l+r)>>1;
	if(ql<=mid&&qr<=mid){
		return querys(o<<1,l,mid,ql,qr)+lazytag[o]*(qr-ql+1);
	}
	if(ql>mid&&qr>mid){
		return querys(o<<1|1,mid+1,r,ql,qr)+lazytag[o]*(qr-ql+1);
	}
	if(ql<=mid&&qr>mid){
		return querys(o<<1,l,mid,ql,mid)+querys(o<<1|1,mid+1,r,mid+1,qr)+lazytag[o]*(qr-ql+1);
	}
}
int main(){
	memset(lazytag,0,sizeof lazytag);
	memset(sumv,0,sizeof sumv);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;++i)cin>>a[i];
	build(1,1,n);
	for(int i=1;i<=m;++i){
		int opt;
		cin>>opt;
		if(opt==1){
			int x,y;ll k;
			cin>>x>>y>>k;
			change2(1,1,n,x,y,k);
		}else{
			int x,y;
			cin>>x>>y;
			cout<<querys(1,1,n,x,y)<<endl;
		}
	}
	return 0;
}

已经a了这道题,但是我这个线段树在区间修改时没有下传标记,而是把上面的部分处理了,并打标记,然后查询时如果查到有标记就直接加上k*(待查询区间长度)

2021/7/19 10:55
加载中...