2022-08-05 树状数组

树状数组:

1、树状数组,又称为二进制索引书(binary indexed Trees),通过二进制划分区间;
2、树状数组引入了分组管理制度,管理数组 c[],c[i]表示每个节点可以管理几个节点;
如图:c[4]管理 a[1~4];就是因为c[] 是树状的,所以称此为树状数组


image.png

1、区间长度:其实就是

如果i的二进制表示末尾有个连续0,那么c[i] 的区间长度为
从a[i]向前个元素 即:

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

2、前驱和后继 概念:

  • 直接前驱: c[i]的直接前驱c[i - lowbit(i)], 即c[i]左侧紧邻的子树的跟
  • 直接后驱:c[i]的直接后驱c[i + lowbit(i)],即c[i]的父节点
  • 前驱:c[i]左侧的所有的子树的根
  • 后驱:c[i]的所有的祖先

3、前缀和:所有的前驱的节点之和

前i个元素的前缀和---i的所有的前驱节点之和
sum[4] = c[4]
-- 4没有前驱
sum[7] = c[7] + c[6] + c[4]
sum[9] = c[9] + c[8]

  //1、求前缀和---持续找前驱
   int sum(int x){
        int sum=0;
        for(int i = x;i != 0;i -= lowbit(i))
            sum += t[i];
        return sum;
    }

4、点更新 ---持续找后继

如果对a[i]更新,那么更新它的所有的祖宗;

    / /2、点更新
    static void add(int x,int k){
        for(int i = x; i <= n;i += lowbit(i))
            t[i] += k;
    }

5、查询区间和

如果要求区间和 就是前j个的前缀和减去前i -1个元素的前缀和
即:
+ 把1~j分为两段;

int sum(int i, int j){
    return sum[j] - sum[i - 1];
}

例题:
https://leetcode.cn/problems/range-sum-query-mutable/
https://www.acwing.com/problem/content/description/243/

你可能感兴趣的:(2022-08-05 树状数组)