算法笔记:树状数组

树状数组的思想原理:前缀和加上类似倍增的思想,相当于前缀和的进阶版

树状数组的序号必须从1开始。

实现原理


每个元素用二进制表示,最右侧的‘1’是储存的区间和的区间长度
lowbit:i&(-i)就是求i的最右边的‘1’

每个元素x储存的区间:[x-lowbit[x]+1,x](理解为:【当前位置-区间长度+1,当前位置】。比如12,储存的就是[9,12]的区间和)

基本应用

正常树状数组:范围查询,单点修改
差分树状数组:范围修改,单点查询

应用实现与原理

前缀和查询(范围[1,i],返回ans):


(i对应的树状数组元素所储存的区间是[i-lowbit[i]+1,i])

1.ans加上i对应的树状数组元素(就是[i-lowbit[i]+1,i]的区间和)

2.i减去lowbit(i)。由于已经算出[i-lowbit[i]+1,i]的区间和,所以将区间缩小到[0,i-lowbit(i)]。如果i==0,说明已经算完了。

代码

int sum(int i){
	int ans = 0;
	while(i>0){
		ans+=tree[i];
		i-=lowbit(i);
	}
	return ans;
}

区间和查询(范围[l,r])

代码

int query(int l,int r){
	return sum(r)-sum(l-1);
}

单点修改(位置i,加上k)

目标就是找到哪些树状数组元素包含这个位置i。

而i+lowbit(i)一定包含i。

代码

void add(int i,int k){
	while(i<=n){
		tree[i]+=k;
		i+=lowbit(i);
	}
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值