树状数组

适用条件:

给定一个规模较大的数组,其中元素变更频繁,随时对数组中所有数的求和。

图中底层为给定数组a,上层为辅助求解的树状数组c,二者之间的关系为 :

当c的下标i为奇数时,c[i] = a[i];

当c的下标i为偶数时,取决于i的因子中最大的一个“2的整数次幂”是多少,如6的因子中为2,则c[6] = a[5] + a[6];

 

求解树状数组:

根据以上分析可写出关系式:c[i] = a[i-2^k+1] + …… + a[i];  那么难点就是求解i所对应的2^k怎么求?

(其中k为i的二进制表示中末尾0的个数,根据右移规律可知,2^k即i的因子中最大的一个“2的整数次幂”)

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

求出c数组后,下面就可对整个数组进行求和了。

 

给定数组求和:

若求数组前6个数和,依据树状图可知sum = c[6] + c[4];

int Sum(int n)
{
    int sum = 0;
    while(n > 0)
    {
        sum += c[n];
        n -= lowbit(n);  // 将n的二进制表示最后一个1的位置减一
    }
    return sum;
}

 

 

修改数组元素:

若对a[5]加上数x,则c[5], c[6], c[8]都要依次调整;

void Change(int i, int x)
{
    while(i <= n)
    {
        c[i] += x;
        i += lowbit(i);  // 将n的二进制表示最后一个1的位置加一
    }
}

 

posted on 2015-07-13 17:30  huashunli  阅读(107)  评论(0编辑  收藏  举报

导航