题解:P3374 【模板】树状数组 1
Alexchen0704 · · 题解
P3374 【模板】树状数组 1(单点修改,区间查询)
铺垫
我们知道,一个数可以分解成多个
我们知道,int lowbit(int n){return n&(-n);}。也就是求一个数二进制末位的
实现方法
我们可以构建一个如上图的树状数组,很显然,当一个编号为
以样例为例,我们就可以得到一个这样的初始树状数组。也就是说,一个节点的值是他所有以这个节点为后继的节点的数值之和。修改也同理,只需要将需要修改的节点的所有后继修改就可以了。这样我们就可以得到修改函数了,平均时间复杂度为
void g(int now,int x){
if(now>n) return;
f[now]+=x;
g(now+lowbit(now),x);
}
查询也同理,如果我们要查询(初始数组)前三个数的和,只需要将树状数组中第二个节点的值与第三个节点的值相加,也就是
unsigned long long co(int x){return x>0?co(x-lowbit(x))+f[x]:0;}
AC代码
#include <bits/stdc++.h>
using namespace std;
unsigned long long f[100000005],n,w,a,b,c,t;
int lowbit(int n){return n&(-n);}
void g(int now,int x){
if(now>n) return;
f[now]+=x;
g(now+lowbit(now),x);
}
unsigned long long co(int x){return x>0?co(x-lowbit(x))+f[x]:0;}
int main(){
cin>>n>>w;
for(int i=1;i<=n;i++){
cin>>t;
g(i,t);
}
for(int i=0;i<w;i++){
cin>>a>>b>>c;
if(a==1){
g(b,c);
}else{
cout<<co(c)-co(b-1)<<endl;
}
}
return 0;
}