ACM -- 树状数组

今天总结一下树状数组。
树状数组刚开始看起来确实难以理解,因为我们通常用的是十进制,但是当我们用二进制来看待数组时,树状数组也就没有那么难以理解了,

首先我们搞明白树状数组是用来干嘛的,现在有一个这样的问题:有一个数组a,下标从0到n-1,现在给你m次修改,n次查询,修改的话是修改数组中某一个元素的值;查询的话是查询数组中任意一个区间的和,m + n < 500000。

下图时树状数组的基本原理

ACM -- 树状数组_第1张图片

起初有一个数组a存放数据,但是为了方便处理上述描述的问题,我们引入一个数组e,
数组e的元素构成情况是:当下表为奇数时,和a对应的下标存放的数据一样,有一个规律就是,当e数组下标转化为二进制时,末尾0的个数就是存放除自身以外数据的个数,

例如:
十进制:2 二进制10 存放数据:e[2] = a[1] + a[2];
十进制:4 二进制100 存放数据:e[4] = a[2] +a[3] +a[4];
十进制:8 二进制1000存放数据:e[8] = a[4] +a[6] +a[7] +a[8];
由此可见2的幂次方存放的数据是上一个幂次方至该幂次方之间下标为偶数的和

其中树状数组中常用的两个函数:

其一:是位运算的函数:
ACM -- 树状数组_第2张图片
下面说一下树状数组下标的定义:

x = x-lowbit(x);
第x元素就是向前数lowbit(X)的元素

下面面是具体实现的代码:
插入操作:

int sum(int x, ArrayInt c, int n)
{
    int ret = 0;
    for ( ; x > 0; ret += c[x], x -= lowbit(x));
    return ret;
}

更新后缀和

void update(int x, int val, ArrayInt c, int n)
{
    for ( ; x <= n; c[x] += val, x += lowbit(x));
}

你可能感兴趣的:(算法,C++,ACM)