修改
void add(int loc,int value){
for (int i=loc;i<=n;i+=i&(-i))
c[i]+=value;
}
查询
int query(int loc){
int ans=0;
for (int i=loc;i>0;i-=i&(-i))
ans+=c[i];
return ans;
}
因为树状数组查询前缀和,所以只能实现区间修改点查询或点修改区间查询
(昨天听课学长说也可以求区间最值蒙逼了)
点修改区间查询(存储点值,查询前缀和相减)
#include<iostream>
#include<cstring>
#include<cstdio>
int n,m,x,y,ty,ans,p,q;
int a[100005],c[100005];
using namespace std;
void add(int loc,int value){
for (int i=loc;i<=n;i+=i&(-i))
c[i]+=value;
}
int query(int loc){
int ans=0;
for (int i=loc;i>0;i-=i&(-i))
ans+=c[i];
return ans;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
for (int i=1;i<=n;++i)
add(i,a[i]);
scanf("%d",&m);
for (int i=1;i<=m;++i){
scanf("%d%d%d",&ty,&x,&y);
if (ty==1)
add(x,y);
else if (ty==2){
p=query(x-1);
q=query(y);
ans=q-p;
printf("%d\n",ans);
}
}
}
区间修改点查询(存储前缀,即当前点与前一点的差值,修改时在区间[l,r]l上加,r+1上减,查询依然是前缀和)
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,ty,a,b,x,ans;
int s[100005],c[100005];
void add(int loc,int value){
for (int i=loc;i<=n;i+=i&(-i))
c[i]+=value;
}
int query(int loc){
int ans=0;
for (int i=loc;i>0;i-=i&(-i))
ans+=c[i];
return ans;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",&s[i]);
for (int i=1;i<=n;++i)
add(i,s[i]-s[i-1]);
scanf("%d",&m);
for (int i=1;i<=m;++i){
scanf("%d%",&ty);
if (ty==1){
scanf("%d%d%d",&a,&b,&x);
add(a,x);
add(b+1,-x);
}
if (ty==2){
scanf("%d",&x);
ans=query(x);
printf("%d\n",ans);
}
}
}