树状数组初步

先说必要性

假设程序中有一个数组,需要求他的前n项和这时需要累加,如果数字很大时可以计算时间复杂度为O(n)。
而且累加的方式是一次性的,如果需要对数据进行更改,那么你需要重新计算所有的数的和。又要进行一次时间复杂度为O(n)的计算。如果有n个数据进行修改,时间复杂度将变为O(n^2)。对此我们引入树状数组。

上图

树状数组初步_第1张图片

先找规律

c1 = a1;
c2 = a1 + a2;
c3 = a3;
c4 = a1 + a2 + a3 + a4;
c5 = a5;
………………
c16 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16;
首先

当i为奇数的时候 ci = ai;

当i为偶数的时候 ci 所包含的个数相当于 本身因子中2的级数的最大次;

上一句话的人话版就是 i转化成二进制从后往前数 有几个零就包含几个a的项;

上公式: cn = (n - a ^ k + 1) + ………………………… + an;

其中a^k的求法为:

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

lowbit函数返回值就是 a ^ k;

用树状数组重新解决开头的问题

累加

1.令sum = 0;
2.sum += cn;
3.n -= lowbit(n);返回第2步;

以上3步为累加上代码;

int sum (int c[], int n)
{
    int sum = 0;
    while(n > 0)
    {
        sum += c[n];
        n -= lowbit(n);
    }
}

数组的某个元素发生变更时

1.当i < n 时 执行2.
2.ci += x, i += lowbit(i) ;返回第一步

int change (int i, int x) // i表示更改的位置, x表示改为的数。
{
    while(i <= n)
    {
        c[i] += x;
        i += lowbit(i);
    }
}

计算一下时间复杂度

你可能感兴趣的:(树状数组)