树状数组的一些认识

 

  int lowbit(int x){  return x&(x^(x–1));

  }

      这个函数的值为2的k次方。形象的就是把二进制的最后一个1和后面的0都拿出来。

      有了形象的感知,函数也就很好理解了。要是把最后一个1和零拿出来,我们先x-1,原先a100...0就变成了a011...1.a异或a为0,所以二进制就变为了000111...1。

      构造线段树的规则的理解,可以从二进制中1的个数来理解。百度百科中,求和和修改的解释是不错的。

      当想要查询一个SUM(n)(求a[n]的和),可以依据如下算法即可:

  step1: 令sum = 0,转第二步;

  step2: 假如n <= 0,算法结束,返回sum值,否则sum = sum + Cn,转第三步;

  step3: 令n = n – lowbit(n),转第二步。

  可以看出,这个算法就是将这一个个区间的和全部加起来,为什么是效率是log(n)的呢?以下给出证明:

  n = n – lowbit(n)这一步实际上等价于将n的二进制的最后一个1减去。而n的二进制里最多有log(n)个1,所以查询效率是log(n)的。

  那么修改呢,修改一个节点,必须修改其所有祖先,最坏情况下为修改第一个元素,最多有log(n)的祖先。

  所以修改算法如下(给某个结点i加上x):

  step1: 当i > n时,算法结束,否则转第二步;

  step2: Ci = Ci + x, i = i + lowbit(i)转第一步。

  i = i +lowbit(i)

     这个过程实际上也只是一个把末尾1补为0的过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值