• 学习笔记 BIT(树状数组)


    痛定思痛,打算切割数据结构,于是乎直接一发BIT
    树状数组能做的题目,线段树都可以解决
    反之则不能,不过树状数组优势在于编码简单和速度更快

    首先了解下树状数组:
    树状数组是一种操作和修改时间复杂度都是O(logN)的数据结构,可以做到  单点修改前缀查询 和 区间修改单点查询
    
    下面来看下树状数组:
    

    万能的树状数组图
    由图发现
    树状数组C[]对应的数组A[]中的值是这样的:
    C【1】=A【1】
    C【2】=C【1】+A【2】=A【1】+A【2】
    C【3】=A【3】
    C【4】=C【2】+A【4】=A【1】+A【2】+A【4】
    ……
    于是乎,神犇们发现了一个性质:
    C【n】=A【n-2^k+1】+……+A【n】(k为n二进制末尾0的个数)
    通常把2^k叫做lowbit
    那么求lowbit的方法:

    int lowbit(int x)
    {
        return x&(-x);//原理是计算机的补码存储方式(反正看不懂且不会考,记住就好)
    }

    查询:
    通过查询前缀和相减即区间和

    int sum(int locate)
    {
        int total=0;
        while (locate>0)
            {
                total+=C[locate];
                locate-=lowbit(locate);
            }
        return total;
    }//前缀和查询

    修改:
    修改需要修改所有和这个有关的点

    void add(int locate,int number)
    {
        while (locate<=n)
            {
                C[locate]+=number;
                locate+=lowbit(locate);
            }
    }//单点修改
     优点是时间复杂度低,但应用面窄,只适合维护求和这一问题,不支持乱搞
    

    区间修改点查询:
    假如说要对[l,r]这个区间的每一个元素加2,那么在l位置加2,在r+1位置减2。查询某个点的权值的时候,查询到该点的前缀和

    二维树状数组:
    或者说 树状数组套树状数组(B格更高)

    void change(int x,int y,int number)
    {
        for (int i=x; i<=n; i+=lowbit(i))
            for (int j=y; j<=n; j+=lowbit(j))
                C[i][j]+=number;
    }
    int sum(int x,int y)
    {
        int total=0;
        for (int i=x; i>0; i-=lowbit(i))
            for (int j=y; j>0; j-=lowbit(j))
                total+=C[i][j];
        return total;
    }

    下面是两个模版题传送门:
    hdu 1166 树状数组模版题:
    http://blog.csdn.net/dad3zz/article/details/49999687
    poj 2155 树状数组套树状数组模版题:
    http://blog.csdn.net/DaD3zZ/article/details/49999777

  • 相关阅读:
    C#线程的IsBackgroud属性动态设置
    asp.net 异步
    IBM一些Java文章
    (一)Apollo配置中心介绍
    样式表中的 element.style样式如何修改
    jquery中的append和js原生中的innerhtml的区别
    如何在datagrid中的column获取json数据
    快速排序
    冒泡排序
    二进制中有多少个1?
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346264.html
Copyright © 2020-2023  润新知