线段树 区间修改 区间查询

感情迁移 提交于 2019-12-02 11:08:46

修改的时候要pushdown 查询的时候也要下放标记

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll maxn=100000+10;
ll tree[maxn<<2],tag[maxn<<2];
int a[maxn],x,y,val;
char s[10];
void pushdown(int node,int len_L,int len_R)
{
	if(tag[node])
	{
		tag[node<<1]+=tag[node];
		tag[node<<1|1]+=tag[node];
		tree[node<<1]+=tag[node]*len_L;
		tree[node<<1|1]+=tag[node]*len_R;
		tag[node]=0;
	}	
}
void creat(int node,int L,int R)
{
	if(L==R)
	{
		tree[node]=a[L];
		return;
	}
	else
	{
		int mid=(L+R)>>1;
		creat(node<<1,L,mid);
		creat(node<<1|1,mid+1,R);
		tree[node]=tree[node<<1|1]+tree[node<<1]; 
	}
}
ll query(int node,int L,int R,int start,int end) // L, R  为查询区间
{
	if(start>R||end<L)
	{
		return 0;
	}
	if(start>=L&&end<=R)
	{
		return tree[node];
	}
	else
	{
		int mid=(start+end)>>1;
		pushdown(node,mid-start+1,end-mid);
		ll lans=0;
		ll rans=0;
		if(mid>=L)
		lans=query(node<<1,L,R,start,mid);
		if(mid+1<=R)
		rans=query(node<<1|1,L,R,mid+1,end);
		return lans+rans;
	}
}
void update(int node,int start,int end,int L,int R,int val)
{
	if(start>R||end<L)
	return;
	if(start>=L&&end<=R)
	{
		tree[node]+=val*(end-start+1);
		tag[node]+=val;
		return ;
	}
	else
	{
		int mid=(start+end)>>1;
		pushdown(node,mid-start+1,end-mid);
		update(node<<1,start,mid,L,R,val);
		update(node<<1|1,mid+1,end,L,R,val);
		tree[node]=tree[node<<1]+tree[node<<1|1]; 
	}
}
int main()
{
	int n,m;	
	scanf("%d %d",&n,&m); 
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	creat(1,1,n);
	for(int  i=0;i<m;i++)
	{
		scanf("%s",s);
		if(s[0]=='Q')
		{
			scanf("%d %d",&x,&y);
			printf("%lld\n",query(1,x,y,1,n));
		}
		if(s[0]=='C')
		{
			scanf("%d %d %d",&x,&y,&val);
			update(1,1,n,x,y,val);
		}
	}	
	return 0;
} 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!