关于树状数组

树状数组的核心在于对一段区间的修改和查询,巧妙地把数组用一颗树表示,从而降低了对数组的修改和查询的复杂度。

首先引入lowbit()

int lowbit(x)

{
  return x & (-x);
}

如:

x =1: 1 &-1

            0000 0001 & 1111 1111 = 1

x = 6:   6  &  -6  

            0000 0110 & 1111 1010 = 2

总结一下就是:

求出某个数二进制表示从右起出现的第一个1及后面的0一起表示的二进制数,如6的二进制表示为110,向左数第一个为0,第二个为1,故Lowbit(6) = 10(2) = 2(10)。

现在看树状数组的图:

我们可以发现没个子节点的父亲节点的下标就是该节点的下标 i + lowbit(i),利用这个特性,我们就可以得到对树状数组的两个操作函数

更新节点:

void Add(int x, int y)
{
    for(int i = x;i <= n;i += lowbit(i))
    {
        c[i] += y;
    }
}

查询区间:

int Sum(int x)
{
    int ans = 0;
    for(int i = x;i > 0;i -= lowbit(i))
    {
        ans += c[i];
    }
    return ans;
}

用这两个函数就可以对树状数组进行更新和查询操作。

原文地址:https://www.cnblogs.com/Lightfall/p/9308125.html