学习笔记 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

转载于:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346264.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值