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;
}