【线段树模板】CodeVS 1082

整理一下标准的线段树模板,区间更新,求区间和两种操作;

还是用数组的方法来表示线段树;

先是定义节点:

struct node{
	long long sum,lazy;	
}c[maxx<<2];

再是建树:(记得l==r时,c[u].sum=a[l],l和r表示的是线段的端点)

void build(int u,int l,int r){
	c[u].lazy=0;
	if(l==r) c[u].sum=a[l];
	else{
		int m=(l+r)/2;
		build(2*u, l, m);
		build(2*u+1, m+1, r);
		c[u].sum=c[2*u].sum+c[2*u+1].sum;
	}
}

然后是pushdown操作:(记得要最后把c[u]的lazy标记清空)

void pushdown(int u,int l,int r){
	int m=(l+r)/2;
	c[2*u].sum+=c[u].lazy*(m-l+1);
	c[2*u].lazy+=c[u].lazy;
	c[2*u+1].sum+=c[u].lazy*(r-m);
	c[2*u+1].lazy+=c[u].lazy;
	c[u].lazy=0;
}

然后是update操作:(sl和sr是当前节点的两端点,l和r是待更新的范围,注意前面两个if的范围,后面要先pushdown把lazy标传递下去才能分治去update,最后求出c[u].sum)

void update(int u,int sl,int sr,int l,int r,int k){
	if(sl>r || sr<l) return ;
	if(sl>=l && sr<=r){
		c[u].lazy+=k;
		c[u].sum+=k*(sr-sl+1);
		return ;
	}
	int m=(sl+sr)/2;
	pushdown(u, sl, sr);
	update(2*u, sl, m, l, r, k);
	update(2*u+1, m+1, sr, l, r, k);
	c[u].sum=c[2*u].sum+c[2*u+1].sum;
	return ;
}

最后是query操作,其实和update操作差不多:(后面记得要先把lazy标签pushdown下去,才能询问儿子节点)

long long query(int u,int sl,int sr,int l,int r){
	if(sl>r || sr<l) return 0;
	if(sl>=l && sr<=r) return c[u].sum;
	pushdown(u, sl, sr);
	int m=(sl+sr)/2;
	return query(2*u, sl, m, l, r)+query(2*u+1, m+1, sr, l, r);
}

主函数(codevs1082):


int main(){
	std::ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	build(1,1,n);
	cin>>m;
	int com,x,y,k;
	while(m--){
		cin>>com;
		if(com==1){
			cin>>x>>y>>k;
			update(1,1,n,x,y,k);
		}
		else if(com==2){
			cin>>x>>y;
			cout<<query(1,1,n,x,y)<<endl;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_33982232/article/details/81273544