• 树状数组(BIT)初学


      BIT(Binary Indexed Tree,BIT) 树状数组。树状数组是一类怎样的数据结构呢?我们知道,树状数组是用来解决动态连续和的查询问题而诞生的。

    数据结构就是说,给你n个元素的数组a[1],a[2],a[3]....a[n](下标要从1开始)然后,支持以下两种操作:

        1.Add(x,y)就是说对下标为x的a[x]加d。模板默认为update(x,y)

        2.Query(L,R)就是计算a[L]+a[L+1]+...+a[R]。模板默认为read(x)求出1-x的和,然后read(y)求出1-y的和,然后再用read(y)-read(x-1)得到[x,y]的和

    所以说,BIT是一种动态的连续和查询问题。

      在学习BIT之前,我们必须对于位运算有一定的认识和了解,我们知道,对于负数来说,在计算机中是以其补码的形式存放的,而补码就是在其原码的基础上,符号位不能发生变化,其余各位取反后加一得到的结果。

      看看这样的运算,比如说7的二进制表示:00000111,那么-7的二进制表示就是:1111001,那么 00000111&11110001的结果是00000001,所以

    这样的运算帮我们找到了7 的二进制表示中,最后一个1的位置,有了这个概念。我们如果进行j-=j&(-j)的运算,就知道了这是在把111->110->100->000的过程了。

    说了这么多了,那就来说说树状数组到底是怎么实现的呢?用tree[].    tree[i]表示的是[i-(i&(-i))+1,i]这个 区间内a数组元素的和 (为什么会是这个,下文会有解释)

    比如我们for( int i = 1;i <= n;i++ )a[i]=i;

    想要求出a[1]~a[15]的元素的值。我们知道15的二进制表示是(1111)2

    tree[15] = sum[15,15];

    tree[14] = sum[13,14];

    tree[12] = sum[9,12];

    tree[8] = sum[1,8]; 

    -> sum[1,15] = tree[1,8]+tree[9,12]+tree[13,14]+tree[15,15];

      为什么会是这样的结果,我们发现,对于结点i来说,如果他是左子结点的话,那么父亲的节点编号就是i+i&(-i)。

    如果i是右子结点的话,那么父亲节点的编号就是i-i&(-i);  

    不难证明,这两个操作的时间复杂度都是O(nlogn),预处理的时候,先把A数组和C数组清空,然后执行n次update()操作,总的时间复杂度是nlogn。

    -read( int pos )求出sum[1,pos]。

    -update( int pos,int v ) 把a[pos]加v

    需要注意的是:更新点然后查询区间,下标必须从1开始。

    如果要是计算sum[l,r]的值,那我们就用read(l)-read(r-1)来实现

    下面来介绍read的两种实现方式.

    第一种,就是用while写的

    int read ( int pos )
    {
        int ans = 0;
        while ( pos>0 )
        {
            ans+=tree[pos];
            pos-=pos&(-pos);
        }
        return ans;
    }

    第二种,使用for写的

    int read ( int pos )
    {
        int ans = 0;
        for ( int j = pos;j;j-=j&(-j) )
        {
            ans+=tree[j];
        }
    }

    再来就是update( int pos,int val )的写法了

    第一种,while写法

    void update( int pos,int val )
    {
        while ( pos <= n )
        {
            tree[pos]+=val;
            pos+=pos&(-pos);
        }
    }

    第二种,for写法

    void update( int pos,int val )
    {
        for ( int j = pos;j <= n;j+=j&(-j) )
        {
            tree[j]+=val;
        }
    }

    根据自己的习惯来写吧,其实都不还可以。

    数据结构学习路线:

    树状数组->堆->线段树->平衡树->可并堆->持久化线段树->树套树(->仙人掌)

  • 相关阅读:
    Android将ScrollView移动到最底部
    Android权限之sharedUserId和签名
    python接口使用及工具函数
    python模块(json、os、sys、random、string、time、hashlib)
    python内置函数
    python模块、函数变量及递归
    python数据类型集合及函数
    python文件操作及修改
    python字符类型操作及文件操作
    jmeter压测
  • 原文地址:https://www.cnblogs.com/wikioibai/p/4394419.html
Copyright © 2020-2023  润新知