现在的位置: 首页 > 综合 > 正文

树状数组

2017年12月13日 ⁄ 综合 ⁄ 共 1234字 ⁄ 字号 评论关闭

        树状数组,我个人理解就是把一个一维的数组,通过转换存在了一个树型的数组里面,从而实现对原数组的快速求和。

        这张图片形象的展示了树状数组的存储结构,

            c[1]=a[1];

            c[2]=a[1]+1[2];

            c[3]=a[3];

            c[4]=a[1]+a[2]+a[3]+a[4];……

        在求和的时候只要对应的求出一些c数组的值就可以求出结果。

        我认为树状数组中最核心的东西是--x&-x,即求x的二进制值中的最低非零位.可以通过这个找到节点的父节点和子节点,

5&-5=1  c[5]的父节点c[6],6-5=1;这样就可以很快的找到树中节点的关系。因为是用一棵树存储的数组空间,并且每个节

点存的是和所以在求和的时候可以省去每一个节点遍历的时间,时间复杂度更低。

        在树状数组上更新一个节点的时间复杂度是o(logn),求和的时间复杂度也是o(logn)。至于怎么证明原理是什么,

我也没弄太明白,我个人的理解就是它这样以二进制的方式存储,每次更新是从本节点开始一直更新父节点,对每个父节

点都加上更新的值,然后我猜可能是因为深度是logn吧~~不太懂,菜鸟我的理论就是当定理背下来,哪天想明白了哪天算,

反正目前没有影响。

template <int SZ>
class BIT{
    int c[SZ+10];
    public :
    void clear(){clr(c,0);}
    void update(int x, int n){   //更新
        while(x<=SZ)
            c[x]+=n,x+=x&-x;      //有的人把这个x&-x拿出来单写了
    }
    int getSum(int x){     //求和
        int s=0;
        while(x>0)
            s+=c[x],x-=x&-x;
        return s;
    }
};

ps:招别人抄的代码,自己理解完了自己写的

..............................................................................................华丽的分割线.............................................................................................................................

树状数组:poj    2352   2299    1195    2481    3067    3321    2309    1990    2155      

                    hdu    1556  

        有部分的题要用到离散化,所为离散化就是把比较分散的数据,转换为一段连续的区间内,比如:1  5  9 三个数字比较离散,我们可以

用着 长 这 来对应的表示,从而达到两极差不是很大。

        有的题还会碰到二维的树状数组,就是用一个c[i]表示一个方块内的和,就是一维的一个扩展。

ps:其实算法就是个脑筋急转弯,想明白了,就明白了……

抱歉!评论已关闭.