树状数组初步

来源:互联网 发布:和平网络电视2.8.9安卓 编辑:程序博客网 时间:2024/06/07 04:53

先说必要性

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

上图

这里写图片描述

先找规律

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);    }}

计算一下时间复杂度

0 0
原创粉丝点击