zoukankan      html  css  js  c++  java
  • 树状数组

    附上学习PPT:传送门

    概念

    树状数组或者二叉索引树也称作Binary Indexed Tree,又叫做Fenwick树;它的查询和修改的时间复杂度都是log(n),空间复杂度则为O(n),这是因为树状数组通过将线性结构转化成树状结构,从而进行跳跃式扫描。通常使用在高效的计算数列的前缀和,区间和。

    其中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

    原理

    lowbit

    它通过公式来得出k,其中k就是该值从末尾开始0的个数。然后将其得出的结果加上x自身就可以得出当前节点的父亲节点的位置或者是x减去其结果就可以得出上一个父亲节点的位置。比如当前是6,二进制就是0110,k为2,那么6+2=8,而C(8)则是C(6)的父亲节点的位置;相反,6-2=4,则是C(6)的上一个父亲节点的位置。

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

    注意:lowbit无法处理0的情况,因为它的结果也是0,那么最终就是一个死循环,所以,树状数组全部设置成以1开始的下标

    单点修改

    当我们要对最底层的值进行更新时,那么它相应的父亲节点存储的和也需要进行更新,所以修改的代码如下:

    //向后修改某一点的值
    void add(int x, int d)
    {
        while(x <= n)
        {
            a[x] += d;
            x += lowbit(x);
        }
    }

    查询

    而查询的时候,则需要向前进行统计

    //向前统计[1, x]的区间和
    int sum(int x)
    {
        int ret = 0;
        while(x > 0)
        {
            ret += a[x];
            x -= lowbit(x);
        }
        return ret;
    }

    注意:

    更新某点a[i] += p;调用add(i, p);

    求区间[x, y]的和调用sum(y) – sum(x - 1);

    例如

    15=(1111)2,通过lowbit分解,它可以变成4个数的和:(1111)2=(1)2+(10)2+(100)2+(1000)2,然后我们分析这个倒着跳的过程。减去15的最小的2的幂次2^0得到14。减去14的最小的2的幂次2^1得到12。减去12的最小的2的幂次2^2得到8。减去8的最小的2的幂次2^3得到0。

    所以C(15) = C(14) + C(12) + C(8) + C(0),由图也可以得知,其结果是正确的。

    除此之外,树状数组能够快速的求任意区间的和,设sum(k) = A[1] + A[2] + ... + A[k],则A[i] + A[i+1] + ... + A[j] = sum(j) - sum(i-1)。

     

    树状数组还有区间修改单点求和的作用

     

     1 int sum(int x)
     2 {
     3     int ret = 0;
     4     while(x <= n)
     5     {
     6         ret += a[x];
     7         x += lowbit(x);
     8     }
     9     return ret;
    10 }
    11 //向前修改[0, x]整个区间加上d
    12 void add(int x, int d)
    13 {
    14     while(x > 0)
    15     {
    16         a[x] += d;
    17         x -= lowbit(x);
    18     }
    19 }
    20 更新某区间,使区间[x, y]加上d调用add(y, d);add(x-1, -d);
    21 求a[x],调用sum(x);

     

     

     

  • 相关阅读:
    java 字符串大小比较
    安卓应用如何赚钱
    报错找不到jquery-1.10.2.min.map解决办法
    android 中 webview 怎么用 localStorage?
    HTML5 本地存储
    js获取url参数值
    java调用webservice
    点圆的关系---1
    数学建模入门书籍介绍
    北京秋日风景-最大的银杏林海景色
  • 原文地址:https://www.cnblogs.com/fzl194/p/8916760.html
Copyright © 2011-2022 走看看