树状数组的总结

仅是个人总结,刚开始学还是看别的博客比较好。我推荐一个比较好的。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;//得到结果

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值