【模板】线段树 区间修改+区间查询

题目大意:维护一个长度为 N 的序列,支持区间修改、区间查询两种操作。

update on 2019.4.3
线段树分为指针式线段树和堆式线段树。指针式线段树的优点是空间较小,可以进行可持久化操作。堆式线段树的优点是可以不必记录左右儿子,缺点是区间要开到四倍,且不能可持久化,不过对于树套树的外层线段树来说,采用堆式线段树看起来更加直观。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;

int n,m;
long long a[maxn];

struct node{
	#define ls(x) t[x].lc
	#define rs(x) t[x].rc
	int lc,rc;
	long long sum,tag;
}t[maxn<<1];
int tot,root;
inline void pushup(int x){
	t[x].sum=t[ls(x)].sum+t[rs(x)].sum;
}
inline void pushdown(int x,int l,int r){
	int mid=l+r>>1;
	t[ls(x)].sum+=(mid-l+1)*t[x].tag,t[ls(x)].tag+=t[x].tag;
	t[rs(x)].sum+=(r-mid)*t[x].tag,t[rs(x)].tag+=t[x].tag;
	t[x].tag=0;
}
int build(int l,int r){
	int x=++tot;
	if(l==r){t[x].sum=a[l];return x;}
	int mid=l+r>>1;
	ls(x)=build(l,mid),rs(x)=build(mid+1,r);
	pushup(x);
	return x;
}
void modify(int o,int l,int r,int x,int y,long long val){
	if(l==x&&r==y){t[o].sum+=(r-l+1)*val,t[o].tag+=val;return;}
	int mid=l+r>>1;
	pushdown(o,l,r);
	if(y<=mid)modify(ls(o),l,mid,x,y,val);
	else if(x>mid)modify(rs(o),mid+1,r,x,y,val);
	else modify(ls(o),l,mid,x,mid,val),modify(rs(o),mid+1,r,mid+1,y,val);
	pushup(o);
}
long long query(int o,int l,int r,int x,int y){
	if(l==x&&r==y)return t[o].sum;
	int mid=l+r>>1;
	pushdown(o,l,r);
	if(y<=mid)return query(ls(o),l,mid,x,y);
	else if(x>mid)return query(rs(o),mid+1,r,x,y);
	else return query(ls(o),l,mid,x,mid)+query(rs(o),mid+1,r,mid+1,y);
}
void read_and_parse(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
	root=build(1,n);
}

void solve(){
	while(m--){
		int opt,val,l,r;
		scanf("%d",&opt);
		if(opt==1){
			scanf("%d%d%d",&l,&r,&val);
			modify(root,1,n,l,r,val);
		}else{
			scanf("%d%d",&l,&r);
			printf("%lld
",query(root,1,n,l,r));
		}
	}
}

int main(){
	read_and_parse();
	solve();
	return 0;
}
#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=1e6+10;
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll read(){
	ll x=0,f=1;char ch;
	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
	return f*x;
}
/*--------------------------------------------------------*/

int n,m,a[maxn];
#define ls(o) o<<1
#define rs(o) o<<1|1
struct node{ll sum,tag;}t[maxn<<2];
inline void pushup(int o){t[o].sum=t[ls(o)].sum+t[rs(o)].sum;}
inline void pushdown(int o,int l,int r){
	int mid=l+r>>1;
	t[ls(o)].sum+=t[o].tag*(mid-l+1),t[ls(o)].tag+=t[o].tag;
	t[rs(o)].sum+=t[o].tag*(r-mid),t[rs(o)].tag+=t[o].tag;
	t[o].tag=0;
}
void build(int o,int l,int r){
	if(l==r){t[o].sum=a[l];return;}
	int mid=l+r>>1;
	build(ls(o),l,mid),build(rs(o),mid+1,r);
	pushup(o);
}
void modify(int o,int l,int r,int x,int y,ll val){
	if(l==x&&r==y){t[o].sum+=val*(r-l+1),t[o].tag+=val;return;}
	int mid=l+r>>1;
	pushdown(o,l,r);
	if(y<=mid)modify(ls(o),l,mid,x,y,val);
	else if(x>mid)modify(rs(o),mid+1,r,x,y,val);
	else modify(ls(o),l,mid,x,mid,val),modify(rs(o),mid+1,r,mid+1,y,val);
	pushup(o);
}
ll query(int o,int l,int r,int x,int y){
	if(l==x&&r==y)return t[o].sum;
	int mid=l+r>>1;
	pushdown(o,l,r);
	if(y<=mid)return query(ls(o),l,mid,x,y);
	else if(x>mid)return query(rs(o),mid+1,r,x,y);
	else return query(ls(o),l,mid,x,mid)+query(rs(o),mid+1,r,mid+1,y);
}

void read_and_parse(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)a[i]=read();
	build(1,1,n);
}

void solve(){
	while(m--){
		int opt=read();
		if(opt==1){
			int l=read(),r=read(),x=read();
			modify(1,1,n,l,r,x);
		}else{
			int l=read(),r=read();
			printf("%lld
",query(1,1,n,l,r));
		}
	}
}

int main(){
	//freopen("D:\学习\Code\对拍\data.in");
	//freopen("D:\学习\Code\对拍\test.out");
	read_and_parse();
	solve();
	return 0;
}

原文地址:https://www.cnblogs.com/wzj-xhjbk/p/9976731.html