树状数组需要一个一维数组,t[pos]表示以pos为最右端点长度为lowbit(pos)的区间的和
如果要改变pos位置的值,与pos位置的值有关的第一个就是t[pos], 第二个是t[pos+lowbit(pos)]:
任意pos1(pos<pos1<pos+lowbit(pos))满足pos1-lowbit(pos1)+1>pos,因为lowbit(pos1)<lowbit(pos),lowbit(pos1)=lowbit(pos1-pos)<=pos1-pos。
所以t[pos1]所对应区间的左端点一定大于pos。
而lowbit(pos+lowbit(pos))>lowbit(pos),即(pos+lowbit(pos))-lowbit(pos+lowbit(pos))+1<=(pos+lowbit(pos))-lowbit(pos),即t[pos+lowbit(pos)]的左端点一定小于等于pos。
于是证明到了与pos的值有关的第二个是t[pos+lowbit(pos)]。
同理,既然t[pos+lowbit(pos)]与pos位置的值有关,就需要更新t[pos+lowbit(pos)],并查找下一个与pos+lowbit(pos)位置的值有关的,那就是
t[(pos+lowbit(pos))+lowbit(pos+lowbit(pos))]........
void chge(int pos,int x){
while(pos<=N) {
t[pos]+=x;
pos+=lb(pos);
}
}
如果要查询从1到pos位置的值的总和
首先加上t[pos],然后剩下的区间变成1到pos-lowbit(pos)。以此类推。
int q(int pos) {
int ans=0;
while(pos>=1) {
ans+=t[pos];
pos-=lb(pos);
}
return ans;
}
所以这样求x到y区间就可以用q(y)-q(x-1)求得
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=500000+10;
int N,M,num[maxn],t[maxn];
int aa,fl;char cc;
int read() {
aa=0;cc=getchar();fl=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') fl=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*fl;
}
int lb(int x){
return x&(-x);
}
void chge(int pos,int x){
while(pos<=N) {
t[pos]+=x;
pos+=lb(pos);
}
}
int q(int pos) {
int ans=0;
while(pos>=1) {
ans+=t[pos];
pos-=lb(pos);
}
return ans;
}
int main() {
N=read();M=read();
int k,x,y;
for(int i=1;i<=N;++i) num[i]=read(),chge(i,num[i]);
for(int i=1;i<=M;++i) {
k=read();x=read();y=read();
if(k==1) chge(x,y);
else printf("%d\n",q(y)-q(x-1));
}
return 0;
}
题目链接2
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=500000+10;
int N,M,num[maxn],t[maxn];
int aa,fl;char cc;
int read() {
aa=0;cc=getchar();fl=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') fl=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*fl;
}
int lb(int x){
return x&(-x);
}
void chge(int pos,int x){
while(pos>=1) {
t[pos]+=x;
pos-=lb(pos);
}
}
int q(int pos) {
int ans=num[pos];
while(pos<=N) {
ans+=t[pos];
pos+=lb(pos);
}
return ans;
}
int main() {
N=read();M=read();
int k,x,y,z;
for(int i=1;i<=N;++i) num[i]=read();
for(int i=1;i<=M;++i) {
k=read();
if(k==1) {
x=read();y=read();z=read();
chge(y,z);chge(x-1,-z);
}
else {
x=read();
printf("%d\n",q(x));
}
}
return 0;
}