線段樹單點修改,區間查詢的模板題

1547:【 例 1】區間和 (信息學一本通網站)

時間限制: 1000 ms         內存限制: 524288 KB
提交數: 1175     通過數: 318 

【題目描述】

給定一數列,規定有兩種操作,一是修改某個元素,二是求區間的連續和。

【輸入】

輸入數據第一行包含兩個正整數n,m(n≤100000,m≤500000),以下是m行,

每行有三個正整數k,a,b(k=0或1,a,b≤n).k=0時表示將a處數字加上b,k=1時表示詢問區間[a,b]內所有數的和。

【輸出】

對於每個詢問輸出對應的答案。

【輸入樣例】

10 20
0 1 10
1 1 4
0 6 6
1 4 10
1 8 9
1 4 9
0 10 2
1 1 8
0 2 10
1 3 9
0 7 8
0 3 10
0 1 1
1 3 8
1 6 9
0 5 5
1 1 8
0 4 2
1 2 8
0 1 1

【輸出樣例】

10
6
0
6
16
6
24
14
50
41

模板題

#include<bits/stdc++.h>
#define N 100000+5
#define LL long long
using namespace std;
int n,m,v;
LL a[N],t[4*N];//線段樹必須爲4*N 空間

//傳入的參數爲 k當前需要建立的結點;l當前需要建立的左端點;r當前需要建立的右端點
void build(int k,int L,int R) {
	if (L==R) t[k]=a[L];//當左端點等於右端點即建立葉子結點時,直接給數組信息賦值
	else {
		int mid = (L+R)/2;
		build(k*2,L,mid);
		build(k*2+1,mid+1,R);
		t[k] = t[k*2] + t[k*2+1];//遞歸返回時用兒子結點更新父節點,此處可進行更新最大值、最小值、區間和等操作
	}
}

//單點修改:
//k、l、r爲當前更新到的結點、左右端點,
//x爲需要修改的葉子結點左端點
//y爲需要修改成的值;
void update(int k,int l,int r,int x,int y) {
	if(l==r) {
		a[x]+=y;
		t[k]+=y;
		return;
	}
	int mid=(l+r)/2;
	if (x>=l&&x<=mid) update(k*2,l,mid,x,y);
	else update(k*2+1,mid+1,r,x,y);
	t[k]=t[k*2]+t[k*2+1];
}

LL query(int k,int l,int r,int x,int y) { //x、y爲需要查詢的區間左右端點
	//若當前結點和需要查找的區間不相交,則返回一個對於區間查詢無關的值
	//(如求和時返回0,求最大值時返回-1等)
	if (x>r||y<l) return 0;
	//若當前結點的區間被需要查詢的區間覆蓋,則返回當前結點的信息
	if (x<=l&&y>=r) return t[k];
	int mid=(l+r)/2;
	//p1爲查詢左兒子結點得到的信息,p2爲查詢右兒子結點得到的信息
	LL p1=query(k*2,l,mid,x,y);
	LL p2=query(k*2+1,mid+1,r,x,y);
	return p1+p2;////綜合兩個兒子結點的信息並返回return p1+p2

}

int main() {
	scanf("%d%d",&n,&m);
	//build(1,1,n);
	while(m--) {
		int k,a,b;
		scanf("%d%d%d",&k,&a,&b);
		if (k==0) {
			update(1,1,n,a,b);
		} else {
			LL ans=query(1,1,n,a,b);
			printf("%lld\n",ans);
		}
	}

	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章