树状数组(单点修改区间查询)
lowbit(重要!)
lowbit是用来取出二进制中最低位数的1所代表的二进制的值。
只需要记下代码就行了
int lowbit(int x){
return x&(-x);
}
add单点修改前缀和
将一个树的最子节点修改,则其父节点也需要更改,父父节点也需要修改。x=x+lowbit(x)就是用来取出其父节点的。
void add(int x,int k){
while(x<=n){
sum[x]+=k;
x=lowbit(x)+x;
}
}
query查询(前缀)和
前缀和
http://106.12.15.69:85/index.php/archives/66/
树状数组中的查询原数组前缀和
能查询原数组的前缀和,时间复杂度为O(nlogn)
查出其中每个范围内最父节点的值并相加
int count(int x){
int cnt=0;
while(x>0){
cnt+=sum[x];
x=x-lowbit(x);
}
return cnt;
}
题目链接
https://www.luogu.org/problemnew/show/P3368
代码
#include<iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
int sum[500010];
int n,m;
int lowbit(int x){
return x&(-x);
}
void add(int x,int k){
while(x<=n){
sum[x]+=k;
x=lowbit(x)+x;
}
}
int count(int x){
int cnt=0;
while(x>0){
cnt+=sum[x];
x=x-lowbit(x);
}
return cnt;
}
int main(){
memset(sum,0,sizeof(sum));
cin>>n>>m;
for(int i=1;i<=n;i++){
int tmp2;
cin>>tmp2;
add(i,tmp2);
}
for(int j=0;j<m;j++){
int s;
cin>>s;
int x,k;
cin>>x>>k;
if(s==1){
add(x,k);
}else{
cout<<count(k)-count(x-1)<<endl;
}
}
return 0;
}