模板-----------线段树的区间修改,区间查询

洛谷3372

#include<iostream>
#include<cstdio>
#include<cstring>
#define re register
#define inl inline
#define LL long long
const int MAXN=2e5+5;
LL f[4*MAXN],a[MAXN],add[4*MAXN];
LL ans,m,n;
inl void build(LL num,LL l,LL r)
{
	if(l==r)
	{
		f[num]=a[l];
		return;
	}
	LL mid=(l+r)>>1;
	build(num*2,l,mid);
	build(num*2+1,mid+1,r);
	f[num]=f[num*2]+f[num*2+1];
}
inl void add_tag(LL num,LL l,LL r,LL tag)
{
	add[num]+=tag;
	f[num]+=(r-l+1)*tag;
	return;
}
inl void pushdown(LL num,LL l,LL r,LL mid)
{
	if(!add[num]) return;
	add_tag(2*num,l,mid,add[num]);
	add_tag(2*num+1,mid+1,r,add[num]);
	add[num]=0;
}
inl void change(LL num,LL l,LL r,LL x,LL y,LL t)
{
	if(x<=l&&r<=y)
	{
		add_tag(num,l,r,t);
		return;
	}
	LL mid=(l+r)>>1;
	pushdown(num,l,r,mid);
	if(x<=mid) change(num*2,l,mid,x,y,t);
	if(mid<y) change(num*2+1,mid+1,r,x,y,t);
	f[num]=f[num*2]+f[num*2+1];
}
inl LL work(LL num,LL l,LL r,LL x,LL y)
{
	if(x<=l&&y>=r) return f[num];
	LL mid=(l+r)>>1,res=0;
	pushdown(num,l,r,mid);
	if(x<=mid) res+=work(num*2,l,mid,x,y);
	if(mid<y) res+=work(num*2+1,mid+1,r,x,y);
	return res;
}
int main()
{
	int ty;
	LL x,y,k;
	scanf("%lld%lld",&n,&m);
	for(re int i=1;i<=n;i++)
	 scanf("%lld",&a[i]);
	build(1,1,n);
	while(m--)
	{
		scanf("%d",&ty);
		if(ty==1)
		{
			scanf("%lld%lld%lld",&x,&y,&k);
			change(1,1,n,x,y,k);
		}
		else 
		{
			scanf("%lld%lld",&x,&y);
			ans=work(1,1,n,x,y);
			printf("%lld\n",ans);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42920131/article/details/85221204