1. 程式人生 > >【線段樹模板】區間修改區間求和

【線段樹模板】區間修改區間求和

蒟蒻線上段樹的路上繼續前進,lazy的出題人的奇思妙想——延遲標記震撼了他。。

線段樹模板題(二)——區間修改與查詢區間和:區間修改區間求和 

【題目描述】  

如題,已知一個數列,你需要進行下面兩種操作:

1.將某區間每一個數加上x

2.求出某區間每一個數的和

【輸入】

第一行包含兩個整數N、M,分別表示該數列數字的個數和操作的總個數。

第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。

接下來M行每行包含3或4個整數,表示一個操作,具體如下:

操作1: 格式:1 x y k 含義:將區間[x,y]內每個數加上k

操作2: 格式:2 x y 含義:輸出區間[x,y]內每個數的和

【輸出】

輸出包含若干行整數,即為所有操作2的結果。

【樣例輸入】

5 5

1 5 4 2 3 2 2 4 1 2 3 2 2 3 4 1 1 5 1 2 1 4                                                  

【樣例輸出】

11

8

20

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define lc (p<<1)
#define rc (p<<1|1)
long long n,m,a[100010]; 
struct node{
	int l,r,lazy;//延遲標記——lazy
	long long sum; 
}T[100010*4];
void pushnow(long long p,long long v){
	T[p].sum+=(T[p].r-T[p].l+1)*v;
	T[p].lazy+=v;
} 
void pushdown(long long p){
	if(T[p].lazy){
		pushnow(lc,T[p].lazy);
		pushnow(rc,T[p].lazy);
		T[p].lazy=0;
	}
}
void pushup(long long p){
	T[p].sum=T[lc].sum+T[rc].sum;
}
void build(long long p,long long l,long long r){//建樹 
	T[p].l=l;
	T[p].r=r;
	if(l==r){
		T[p].sum=a[l];
		T[p].lazy=0;
		return ;
	}
	long long mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	pushup(p); 
}
void update(long long p,long long ql,long long qr,long long v){//向上維護 
	if(ql<=T[p].l&&T[p].r<=qr){
		pushnow(p,v);
		return ;
	}
	long long mid=(T[p].l+T[p].r)>>1;
	pushdown(p);
	if(ql<=mid)
		update(lc,ql,qr,v);
	if(qr>mid)
		update(rc,ql,qr,v);
	pushup(p);
} 
long long query(long long p,long long ql,long qr){//區間求和 
	if(ql<=T[p].l&&qr>=T[p].r)
		return T[p].sum;
	long long mid=(T[p].l+T[p].r)>>1;
	pushdown(p);
	long long ans=0;
	if(ql<=mid)
		ans+=query(lc,ql,qr);
	if(qr>mid)
		ans+=query(rc,ql,qr);
	pushup(p);
	return ans; 
} 
int main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	build(1,1,100100);
	for(long long i=1;i<=m;i++){
		long long p;
		scanf("%lld",&p);
		if(p==1){
			long long x,y,k;
			scanf("%lld%lld%lld",&x,&y,&k);
			update(1,x,y,k);
		}
		if(p==2){
			long long x,y;
			scanf("%lld%lld",&x,&y);
			printf("%lld\n",query(1,x,y));
		}
	} 
	return 0; 
}