• 树状数组


        首先,我们需要了解一下数在计算机中的储存方式。

    以68为例,他的二进制是(68)2=1000100. 那么-68呢?因为计算机里的整数采用补码表示(补码是原码取反加一),因此-68实际上是68按位取反,末尾加一以后的结果。如下表(忽略符号位):

    原码   1 0 0 0 1 0 0

              ↓

    反码   0 1 1 1 0 1 1

             ↓

    补码   0 1 1 1 1 0 0

    我们把(68)2和(-68)2放在一起看一看:

    1 0 0 0 1 0 0

    0 1 1 1 1 0 0

    发现他们末尾带的0是一样多的。因此lowbit(x)=x&-x.   (&是转换成二进制之后进行与运算;而&&是直接进行与运算)


    下面是一个比较经典的树状数组(BIT):

     

    ↓     ↓     ↓     ↓    ↓     

     lowbit   =   24   23     22   21   20                                  

    从图中可以得到以下规律:

    1)对于结点i,如果他是左子结点(下左上右),那么他父节点的编号就是i+lowbit(i);如果他是右子节点,那么他父节点的编号就是i-lowbit(i)。(i>=lowbit(i))

    2)奇数的lowbit之所以都是1,是因为他们的二进制个位就是1(即因数没有2)。后面的以此类推:2、6、10、14只能整除21,4、12可以整除22……因此他们的lowbit依次是2、3……

    在以上规律的基础上,我们新建一个数组C(A是原数组),则易得:

    Ci=Ai-lowbit(i)+1+Ai-lowbit(i)+2+……+Ai

    举例:C1=A1,C2=A1+A2,C3=A3,C4=A1+A2+A3+A4,……


     接下来是一些应用:

    1)求前缀和Si:顺着结点i向上,依次找到i左上侧的每个结点j,每个结点的Cj加起来即为结点i的前缀和(如下图)。

    2)更新数据:如果修改了一个Ai,如何计算前缀和Si?顺着结点i向上,依次找到i右上侧的每个结点j,修改每个结点的Cj 即可。

  • 相关阅读:
    java.lang.NoClassDefFoundError: TagSupport 错误
    ${pageContext.request.contextPath}的作用
    JS获取table表格任意单元格值
    数据库导出为Excel
    requestScope含义
    每种创伤,都是另一种成熟
    关于AJAX
    the public type xxx must be defined in its own file
    MyEclipse取消Show in Breadcrumb的方法
    Sql2005里获取表的结构SQL
  • 原文地址:https://www.cnblogs.com/YXY-1211/p/7114799.html
Copyright © 2020-2023  润新知