树状数组学习总结

来源:互联网 发布:苹果手机关闭移动数据 编辑:程序博客网 时间:2024/05/03 16:36

树状数组最大的特点就是求解特定区间的元素的和操作时间复杂度小O(lgn),现对于传统的顺序求和的操作树状数组在求解过程中采用了二进制的思想,巧妙地化解了多次求和的重复操作,在很大程度上提高了效率。

上图是树状数组的存储于求解过程,图片给出的很详细,数组a存放的是原始的需要求和的元素,数组c存放的是利用二进制存储的各部分的和。

在控制各部分求和的过程中有这样的过程操作,

C1 = A1 
C2 = A1 + A2 
C3 = A3 
C4 = A1 + A2 + A3 + A4 
C5 = A5 
C6 = A5 + A6

C7 = A7 
C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 
…… 
C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16 
所采用的计算过程是主要是二进制思想;

其中求二进制操作的过程可用下面操作完成

int lowbit(int x)
{
    return x&(-x); //找出x的二进制表示的末尾有多少个0,但是我感觉这么说很不妥当的,这个操作的主要作用

//就是可以实现2^k的操作,或者说是二进制表示的做右侧的1的位置
}

其次在存储的过程中还需要一个操作来初始化数组c

void change(int i,int x)
{
    while(i<=maxn)
    {
         c[i]+=x;
        i+=lowbit(i);
    }
}

再输入数组a的同时就需要对数组c进行初始化,以及进行后续的与ci相关联的c数组元素进行修改,以保证c数组中存储的一直都是最新的变更之后的值,此外对于初学者,在看这部分的时候可能会有点迷惑,所以可以尝试在每一次变更的过程中查看i的值的变化,来更好的理解其中变化的规律。

其次最终额操作就是求前i项的和的操作了,

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

与上边change操作的相似度很大,只不过是  x-=lowbit(x);这个操作的目的是保证取出数组c中x之前的元素的和.

0 0
原创粉丝点击