zoukankan      html  css  js  c++  java
  • 树状数组

    树状数组又称二叉索引树(Binary Indexed Tree),1994年由Fenwick发明。多用于高效计算数列的前缀和区间和。可以以(O(log n))的时间得到任意前缀和,并且可以在(O(log n))时间内修改单点的值。其空间复杂度是(O(n))

    思想

    我们有一个数组 A,对它进行如下构造,构造出一个如下的树状数组 C。

    image-20211107143746874

    其中C[i]等于与它连线的元素相加:

    C1 = A1;
    C2 = A1+A2;
    C3 = A3;
    C4 = A1+A2+A3+A4;
    ......

    我们定义一个函数 lowbit(i) :表示二进制数 i 的低位第一个非零1代表的数。如 2(0010) 的 lowbit 为 (10_{2});3(0011) 的 lowbit 为 (1_{2});8(1000) 的 lowbit 为 (1000_{2})

    我们可以发现,C[i] 是由一些连续的A[i]、A[i-1]、A[i-2]...相加得来的。具体是多少个连续的A[j]相加呢,就是数组C的下标的lowbit个,比如:C2 = A1+A2,C2的lowbit是2;C3 = A3,C3的lowbit是1; C4 = A1+...+A4,C4的lowbit是4。因此可以得到如下的关系式:

    [C[i] = sum_{j=i-lowbit(i)+1}^{i}{A[j]} ]

    有了关系式我们就可以构造出树状数组C了。

    这样在求前缀和S[i]时,我们不用去求A[1]+...+A[i],而是可以通过数组C来求。

    比如求S[4],即是C[4];S[6] = C[6] + C[4];S[8] = C[8]。可以看到,这大大降低了求前缀和的复杂度。

    树状数组的思想就是:所有的整数都可以表示成2的幂和,我们也可以把一串序列表示成一系列子序列的和。采用这个想法,我们可将一个前缀和划分成多个子序列的和,而划分的方法与二分非常相似。

    基本方法

    变量说明:原数组 A,树状数组 BIT

    注意,通常我们会让 A[0]、BIT[0]都为空,从下标1开始存放数据,这会让编程更方便。因此下面给出的方法都是这样假定的。具体使用时你可以根据需要做一些小心的下标变换,改成从下标0开始

    lowbit

    在计算机中计算 lowbit 有非常高效的位运算:lowbit(x) = x & -x

    int lowbit(int x){
      return x&(-x);
    }
    

    初始化 BIT

    void init(){
      for (int i = 1; i <= A.length; i++) {
        BIT[i] = A[i];
        for (int j = i - 1; j > i - lowbit(i); j -= lowbit(j)){
          BIT[i] += BIT[j];
        }
      }
    }
    

    单点修改

    // 将A[i]的值增加 delta
    void add(int i,int delta){
      for(int j=i; j<=A.length; j+=lowbit(j))
        BIT[j] += delta;
    }
    

    求前缀和

    // 求下标 k 的前缀和
    int sum(int k){
      int ans=0;
      for(int i=k; i>0; i-=lowbit(i))
        ans+=BIT[i];
      return ans;
    }
    

    参考:https://zh.wikipedia.org/wiki/树状数组

  • 相关阅读:
    SpringMvc上手学习
    UITapGestureRecognizer 和 UICollectionView、UITableView的点击事件冲突问题
    Omnigraffle 许可证
    REACT-NATIVE
    iOS @property、@synthesize和@dynamic
    WWDC2018 之 优化 App Assets Optimizing App Assets
    WWDC2018 之 高性能 Auto Layout
    链表
    Your development team, "", does not support the Push Notifications capability.
    xcode无线调试
  • 原文地址:https://www.cnblogs.com/cpcpp/p/15520167.html
Copyright © 2011-2022 走看看