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

    隆重介绍一个优秀的数据结构!!

    它不像分块那样笨重——

    它不像线段树那样复杂——

    它拥有着logn的复杂度——

    它可以快速算出逆序对数量——

    树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询)。

    原理

    首先我们要了解计算机反码与补码:

    计算机界是不存在减法的——有正负号的类型int 首位存储正负号。这也就是int比unsigned int多消耗一个位数的原因。

    反码相当于把所有的数字按位取反 再加1。

    举个例子:

    (此处把32位二进制数简写成8位)

    8-5=3

    写成二进制就是

    0 0 0 0 1 0 0 0

    + 1 1 1 1 1 0 1 1 (5的反码)

    1 0 0 0 0 0 0 1 1

    首位废弃,得到(11)2=(3)10

     

    树状数组中,

    s[1]=a[1]

    s[2]=a[1]+a[2]

    s[3]=a[3]

    s[4]=a[1]+a[2]+a[3]+a[4]

    转化成二进制就是:

    s[1]=a[1]

    s[10]=a[1]+a[10]

    s[11]=a[11]

    s[100]=a[1]+a[10]+a[11]+a[100]

    当我们已经从下至上地建树之后,求前n项的和只需由上加到下就好了:

    前一(1)项和:s[1]=s[1]

    前两(10)项和:s[2]=s[10]

    前三(11)项和:s[2]+s[3]=s[10]+s[11]

    前四(100)项和:s[4]=s[100]

    写到这里,规律已经变得非常明显了。

    从下到上是i加上最低位的1所得的值,从上到下则是从减去最低为的1的值。

    取出最低位的1

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

    查询

    int getsum(int x){
        int ans = 0;
        for(;x;x-=lowbit(x))
            ans += s[x];
        return ans;
    }

    单点更新

    1 void update(int x, int y){  
    2     for(;x<=n;x+=lowbit(x))
    3     s[i] += y;
    4 }
  • 相关阅读:
    反向代理实例
    nginx常用命令和配置
    nginx的安装
    Can Live View boot up images acquired from 64bit OS evidence?
    What is the behavior of lnk files?
    EnCase v7 search hits in compound files?
    How to search compound files
    iOS 8.3 JB ready
    Sunglasses
    现代福尔摩斯
  • 原文地址:https://www.cnblogs.com/hnoi/p/10922607.html
Copyright © 2011-2022 走看看