社区讨论

蒟蒻求改

P3372【模板】线段树 1参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@lo2a9x50
此快照首次捕获于
2023/10/23 10:33
2 年前
此快照最后确认于
2023/11/03 10:45
2 年前
查看原帖
CPP
#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int Kmax=1e5+5;

int n,m,s[Kmax]; 
ll ans;
struct tree{
	int l,r;//区间的范围 l-r
	ll zhi,lazy; 
}tre[Kmax*4+5];


void bulid(int p,int l,int r){
	tre[p].l=l,tre[p].r=r;
	if(l==r){//只有一个值 赋值 
		tre[p].zhi=s[l];
		return;
	}
	//否则 中分 两边分别处理
	// 再将得出的数累计
	int zhong=(l+r)/2;
	bulid(p*2,l,zhong);//左儿子 
	bulid(p*2+1,zhong+1,r);//右儿子 
	tre[p].zhi=tre[p*2].zhi+tre[p*2+1].zhi;
	//结果 
}

void xc(int p){
	if(tre[p].lazy){
		tre[p*2].zhi+=tre[p].lazy*(tre[p*2].r-tre[p*2].l+1);
		tre[p*2+1].zhi+=tre[p].lazy*(tre[p*2+1].r-tre[p*2+1].l+1);//为左右儿子累加值 
        tre[p*2].lazy+=tre[p].lazy;
		tre[p*2+1].lazy+=tre[p].lazy;//给左右儿子也打上标记 
        tre[p].lazy=0;
	} 
}

void change(int p,int x,int y,int k){
	if(x<=tre[p].l&&tre[p].r<=y){
		tre[p].zhi+=(ll)k*(tre[p].r-tre[p].l+1);//每份增加的值*份数 
		tre[p].lazy+=k;//打上标记
		return; 
	}
	xc(p);
	int zhong=(tre[p].l+tre[p].r)/2;  //中点 
	if(x<=zhong) change(p*2,x,y,k);
	if(y>zhong) change(p*2+1,x,y,k);//继续传递 
	tre[p].zhi=tre[p*2].zhi+tre[p*2+1].zhi;//更新总值 
} 

ll ask(int p,int x,int y){
	if(x<=tre[p].l&&tre[p].r<=y) return tre[p].zhi;
	xc(p);
	int zhong=(tre[p].l+tre[p].r)/2;
	ans=0;
	if(x<=zhong) ans+=ask(p*2,x,y);
	if(y>zhong) ans+=ask(p*2+1,x,y);
	return ans;
}

int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>s[i];
	}
	bulid(1,1,n);//建树操作   处理的位置 l r 
	int t,x,y,k;
	while(m--){
		cin>>t;
		if(t==1){
			cin>>x>>y>>k;
//			change(1,x,y,k);//修改(增加k) 
			//“ 1  ” 是开始查找的位置 
		}else{
			cin>>x>>y;
			cout<<ask(1,x,y)<<endl;
		}
	}
} 

回复

3 条回复,欢迎继续交流。

正在加载回复...