仅是个人总结,刚开始学还是看别的博客比较好。我推荐一个比较好的。https://blog.csdn.net/qq_39553725/article/details/76696168
一:单点修改,区间查询(常见树状数组的基本用法)
int a[maxn],c[maxn],n;//a是记录原值的数组,c就是树状数组,n表示的是个数
int lowbit(int x){ return x&(-x); }
int sum(int r){
int ans=0;
for(r;r>0;r-=lowbit(r)) ans+=c[i];
return ans;
}
void update(int x,int v){
for(int i=x;i<=n;i+=lownbit(i)) c[i]+=v;
}
update(x,v);//将x位置增加v
int ans=sum(r)-sum(l-1);//区间查询[l,r]之间的和
二:区间修改,单点查询(这个树状数组跟三的区间修改区间查询不同。poj2155二维树状数组用的就是这个思想,我们在这只说一维。)
int a[maxn],c[maxn],n;//a是记录原值的数组,c就是树状数组,n表示的是个数
int lowbit(int x){ return x&(-x); }
int sum(int r){
int ans=0;
for(r;r>0;r-=lowbit(r)) ans+=c[i];
return ans;
}
void update(int x,int v){
for(int i=x;i<=n;i+=lownbit(i)) c[i]+=v;
}
update(l,v);
update(r+1,-v);//完成一次[l,r]的区间更新
int ans=sum(x);//完成一次对x点的查询
为啥求和与更新的函数都不变,但是参数变了?
比如初始化位置1 2 3 4上面的值都是 0,即是0 0 0 0
然后我让[2,3]区间+5。
update(2,5)这个时候会变成0 5 0 5。
update(4,-5)会使数列的值变成0 5 0 0
这个时候sum(2)=sum(3)=5,sum(1)=sum(4)=0;
其实就是因为树状数组更新的时候是向后更新的。update(2,5)会影响到4位置的值,所以后面要有update(4,-5)消除影响。因为我们是把前缀和作为单点的值,所以只能查询单点的值,而不能查询区间的值。
http://poj.org/problem?id=2155poj2155 二维树状数组
三:区间查询,区间修改
int c1[maxn],c2[maxn],n;
int lowbit(int x) { return x&(-x); }
int sum(int a[],int x){
int ans=0;
for(int i=x;i>0;i-=lowbit(i)) ans+=a[i];
return ans;
}
void update(int a[],int x,int v){
for(x;x<=n;x+=lowbit(x)) a[x]+=v;
}
//c1是a[i]-a[i-1]为元素的树状数组
//c2是(i-1)(a[i]-a[i-1])为元素的树状数组
update(c1,l,v);
update(c1,r+1,-v);
update(c2,l,v*(l-1));
update(c2,r+1,-v*(r));//将[l,r]区间都加上v的操作执行完毕
int sum1=r*sum(c1,r)-sum(c2,r);
int sum2=(l-1)*sum(c1,l-1)-sum(c2,l-1);
int ans=sum1-sum2;//得到结果