题目
思路
一、树状数组
1.单点修改,区间查询: < O(logn)。
2.代码量小于线段树,但功能不如线段树多。
3.查询只支持1~i的和,所以求区间和要用前缀和的形式。
4.需要空间更小,只用O(n)
(具体树状数组的代码实现是固定的,看代码)
代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#define _for(i,a,b) for(int i = a; i<b; i++)
#define _rep(i,a,b) for(int i = a; i<=b; i++)
using namespace std;
const int maxn = 100000+10;
int n,m,t[maxn];
int lowbit(int x) { return (x&(-x)); }
void add(int x, int y){
while (x<=n){
t[x] += y;
x += lowbit(x);
}
}
int find(int x){ // 树状数组只支持从1到i的区间和,所以查询时应该使用前缀和
int res = 0;
while(x){
res+=t[x];
x-=lowbit(x);
}
return res;
}
int main(){
scanf("%d",&n);
int u;
_rep(i,1,n){
scanf("%d",&u);
add(i,u);
}
scanf("%d",&m);
int a,b,c;
while(m--){
scanf("%d%d%d",&a,&b,&c);
if(a==1){
add(b,c);
} else {
printf("%d\n",find(c)-find(b-1)); // 这里前缀和,是find(c)-find(b-1)而不是find(c)-find(b)
}
}
return 0;
}