P3372 【模板】线段树 1 常规做法

题目

P3372 【模板】线段树 1 常规做法_第1张图片

思路

普普通通的线段树做法

代码

#include
using namespace std;
const int M=1e5+5;
#define lc(x) ((x)<<1)
#define rc(x) ((x)<<1|1)
#define int long long
int n,m;
int a[M],sm[M<<2],tag[M<<2];
void pushup(int x) { sm[x]=sm[lc(x)]+sm[rc(x)]; }
void build(int p,int l,int r){
	if(l==r) { sm[p]=a[l];return; }
	int mid=(l+r)>>1;
	build(lc(p),l,mid),build(rc(p),mid+1,r);
	pushup(p);
}
void f(int p,int l,int r,int k) { tag[p]+=k;sm[p]+=k*(r-l+1); }
void pushdown(int p,int l,int r) { int mid=(l+r)>>1;f(lc(p),l,mid,tag[p]),f(rc(p),mid+1,r,tag[p]),tag[p]=0; }
void update(int nl,int nr,int l,int r,int p,int k){
	if(nl<=l&&r<=nr) { f(p,l,r,k);return; }
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if(nl<=mid) update(nl,nr,l,mid,lc(p),k);
	if(mid<nr) update(nl,nr,mid+1,r,rc(p),k);
	pushup(p);
}
int query(int qx,int qy,int l,int r,int p){
	int ans=0;
	if(qx<=l&&r<=qy) return sm[p];
	int mid=(l+r)>>1;
	pushdown(p,l,r);
	if(qx<=mid) ans+=query(qx,qy,l,mid,lc(p));
	if(mid<qy) ans+=query(qx,qy,mid+1,r,rc(p));
	return ans;
}
signed main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	while(m--){
		int if_case;
		cin>>if_case;
		int x,y,k;
		switch (if_case){
			case 1:cin>>x>>y>>k;update(x,y,1,n,1,k);break;
			case 2:cin>>x>>y;cout<<query(x,y,1,n,1)<<endl;break;
		}
	}
	return 0;
}

你可能感兴趣的:(算法,数据结构,线段树,c++)