P3374 【模板】树状数组 1
P3374 【模板】树状数组 1
时间限制 1.00s
内存限制 125.00MB
题目描述
如题,已知一个数列,你需要进行下面两种操作:
- 将某一个数加上\(x\)
- 求出某区间每一个数的和
输入格式
第一行包含两个正整数\(n,m\),分别表示该数列数字的个数和操作的总个数。
第二行包含\(n\)个用空格分隔的整数,其中第\(i\)个数字表示数列第\(i\)项的初始值。
接下来\(m\)行每行包含\(3\)个整数,表示一个操作,具体如下:
1 x k
含义:将第\(x\)个数加上\(k\)2 x y
含义:输出区间\([x,y]\)内每个数的和
输出格式
输出包含若干行整数,即为所有操作\(2\)的结果。
输入输出样例
输入 #1
5 5
1 5 4 2 3
1 1 3
2 2 5
1 3 -1
1 4 2
2 1 4
输出 #1
14
16
说明/提示
【数据范围】
对于\(30\%\)的数据,\(1 \le n \le 8\),\(1\le m \le 10\);
对于\(70\%\)的数据,\(1\le n,m \le 10^4\);
对于\(100\%\)的数据,\(1\le n,m \le 5\times 10^5\)。
样例说明:
故输出结果\(14\)、\(16\)
推荐皎月半洒花的Senior Data Structure高级数据结构初步·详解分块思想与树状数组
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=5e5+5;
int n,m,c[N];
int lowbit(int x){ return x&(-x); }
void add(int i,int x){
while(i<=n){
c[i]+=x;
i+=lowbit(i);
}
}
int check(int i){
int res=0;
while(i){
res+=c[i];
i-=lowbit(i);
}
return res;
}
int main(){
scanf("%d %d",&n,&m);
for(int x,i=1;i<=n;++i){
scanf("%d",&x);
add(i,x);
}
for(int x,y,opt,i=1;i<=m;++i){
scanf("%d",&opt);
if(opt==1){
scanf("%d %d",&x,&y);
add(x,y);
} else {
scanf("%d %d",&x,&y);
printf("%d\n",check(y)-check(x-1));
}
}
return 0;
}