树状数组的简单实现和原理::

树状数组的概念:

树状数组或者二叉索引树也称作Binary Indexed Tree,又叫做Fenwick树;它的查询和修改的时间复杂度都是log(n),空间复杂度则为O(n),这是因为树状数组通过将线性结构转化成树状结构,从而进行跳跃式扫描。通常使用在高效的计算数列的前缀和,区间和

int c[maxn];

其中A数组就是原数组,C数组则是树状数组,可以发现
(0001) C1 = A1
(0010) C2 = A1+A2
(0011) C3 = A3
(0100) C4 = A1+A2+A3+A4
(0101) C5 = A5
(0110) C6 = A5+A6
(0111) C7 = A7
(1000) C8 = A1+A2+A3+A4+A5+A6+A7+A8

原理

lowbit

它通过公式来得出k,其中k就是该值从末尾开始0的个数。而C[n]中的元素则有2^k(此时k为对应n的二进制数末尾的0的个数), 然后将其得出的结果加上x自身就可以得出当前节点的父亲节点的位置或者是x减去其结果就可以得出上一个父亲节点的位置。比如当前是6,二进制就是0110,k为2,那么6+2=8,而C(8)则是C(6)的父亲节点的位置;相反,6-2=4,则是C(6)的上一个父亲节点的位置。

int lowbit(int x){//求2^k;
	return x&(-x);
}

!注意!:LOWBIT无法处理0的情况,因为它的结果也是0,那么最终就是一个死循环

好,下面我们开始增加元素:

int add(int x, int v) //在x的位置增加元素v
{
	while (x < maxn)
	{
		c[x] += v;
		x += lowbit(x);
	}
}

求和:

int sum(int x) 
{
	int ret = 0;
	while (x > 0) //往下查找
	{
		ret += c[x];
		x -= lowbit(x);
	}
	return ret;
}

下面我引用的一点:

15=(1111)2,通过lowbit分解,它可以变成4个数的和:(1111)2=(1)2+(10)2+(100)2+(1000)2,然后我们分析这个倒着跳的过程。
减去15的最小的2的幂次2^0 得到14。
减去14的最小的2的幂次2^1得到12。
减去12的最小的2的幂次2^2得到8。
减去8的最小的2的幂次2^3得到0。
所以C(15) = C(14) + C(12) + C(8) + C(0),由图也可以得知,其结果是正确的。
除此之外,树状数组能够快速的求任意区间的和,设sum(k) = A[1] + A[2] + … + A[k],则A[i] + A[i+1] + … + A[j] = sum(j) - sum(i-1)
所以单点查询为:sum[x] - sum[x-1];

其它的以后我再补充啊!!!吃饭要紧!!!!。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值