【Data Structure】树状数组

      对于区间信息进行快速查询是设计许多程序需要实现的功能,树状数组是属于其中比较简单的一种数据结构,其主要功能有查询前缀和与更新数据。


      对于树状的东西,一般又离不开2和二进制,这里我们需要引入一个lowbit的概念。对于每个数组编号,我们可以求出其最低有效位的大小,数学上,数组编号的中心将会成为根(它的lowbit最高)。通过lowbit我们把相对对称的位置取到了同一高度(这里的数学证明暂且不管)。这棵树具有的性质是左节点加上自己的lowbit是父节点编号,而右节点则是减去。下面是求lowbit的代码:

int lowbit(int x)
{
    int result=1;
    while(!(1&x))
    {
        x>>=1;
        result<<=1;
    }
    return result;
}

     下面就要说说add操作了,我们如果对某个原始数据加上了d,那么所有包含该数据的区间就都应该加上d。如何操作呢?我们用一个C数组来储存这样一个信息:C[x]表示以x结尾,长度为lowbit(x)区间上的和。这样我们可以发现,每次更新位置为x的原始数据,在lowbit(x)之下的值都不用更新了。也就是从x往上更新就可以了,注意不要超过最大范围:

void add(int x,int d)
{
    while(x<=MAX)
    {
        c[x]+=d;
        x+=lowbit(x);
    }
}
     查询也并不难,只要把x之前所有和加起来就行了,方法是沿着儿子一步步向下走:

int query(int x)
{
    int res=0;
    while(x>0)
    {
        res+=c[x];
        x-=lowbit(x);
    }
    return res;
}

     至此,树状数组的基本功能就全部实现了。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值