洛谷 P3372 【模板】线段树 区间修改 区间求和

因为忘了把lazy tag置零,找了一晚上的bug终于AC了QWQ

#include<bits/stdc++.h>
#define ll long long
#define maxn 20000000
using namespace std;
ll n, m, a[maxn];

struct tree{
	ll l, r, val, tag;//l左端点, r右端点, val区间值, tag懒标记 (lazy tag) 
}tr[maxn];

//向下更新 
void down(ll p){
	ll mid = (tr[p].l + tr[p].r)>>1;
	
	//给左右孩子加上双亲的懒标记 
	tr[p<<1].tag  += tr[p].tag;		//p<<1相当于p*2 
	tr[p<<1|1].tag += tr[p].tag;	//p<<1|1相当于p*2+1 
	
	//根据懒标记更新左右孩子的区间值 
	tr[p<<1].val += tr[p].tag * (mid-tr[p].l+1);
	tr[p<<1|1].val += tr[p].tag * (tr[p].r-mid);
	
	//左右孩子更新完毕,将双亲的懒标记归零   
	tr[p].tag = 0;
}

//向上更新 
void up(ll p){
	//根据左右孩子的区间值更新双亲结点的区间值 
	tr[p].val = tr[p<<1].val + tr[p<<1|1].val;
}

//初始化建树 
void buildTree(ll p, ll l, ll r){ 
	tr[p].l = l, tr[p].r = r, tr[p].tag = 0, tr[p].val = 0;	
	
	if(l==r){
		tr[p].val = a[l];
		return;
	}
	
	ll mid = (l+r)>>1;	//相当于(l+r)/2 
	buildTree(p<<1, l, mid);	//左孩子 
	buildTree(p<<1|1, mid+1, r);//有孩子 
	up(p);
}


//区间修改 (p为tr数组下标,在[l, r] + w) 
void add(ll p, ll l, ll r, ll w){
	if(tr[p].l>=l&&tr[p].r<=r){	//若tr[p]在[l, r]修改范围内 
		tr[p].tag += w;
		tr[p].val += w * (tr[p].r - tr[p].l + 1);
		return;
	}
	
	down(p);	
	
	ll mid = (tr[p].r+tr[p].l)>>1;
	if(l<=mid)
		add(p<<1, l, r, w);
	if(r>mid)
		add(p<<1|1, l, r, w);
		
	up(p);		
}

//获取[l, r]区间的和 (p为tr数组下标)
ll get(ll p, ll l, ll r){
	ll ans = 0; 
	
	if(tr[p].l>=l&&tr[p].r<=r)//若tr[p]在[l, r]求和范围内 
		return tr[p].val;
	
	down(p);

	ll mid = (tr[p].r+tr[p].l)>>1;
	if(l<=mid)
		ans += get(p<<1, l, r); 		
	if(r>mid)
		ans += get(p<<1|1, l, r);
	
	return ans;
}

//调试用的打印tr数组 
void printTree(){
	printf("\n");
	for(ll i=1; i<=2*n-1; i++)
		printf("%lld %lld %lld %lld\n", tr[i].l, tr[i].r, tr[i].val, tr[i].tag);
	printf("\n");
}

int main(){
	int t;
	ll x, y, k;
	cin>>n>>m;
	
	for(ll i=1; i<=n; i++)
		scanf("%lld", &a[i]);

	buildTree(1, 1, n);	
	
	for(ll i=0; i<m; i++){
		scanf("%d", &t);
		if(t==1){
			scanf("%lld %lld %lld", &x, &y, &k);
			add(1, x, y, k);
		}else{
			scanf("%lld %lld", &x, &y);
			printf("%lld\n", get(1, x, y));
		}
	}
	return 0 ;	
} 
发布了46 篇原创文章 · 获赞 1 · 访问量 2399

猜你喜欢

转载自blog.csdn.net/weixin_43708069/article/details/104664613