树状数组

    在做2014年蓝桥杯的题目时,第10题说是要用到树状数组,于是就查了一下。

    树状数组这个结构是在设计压缩算法时被发现的。


    树状数组的基础是一个被构造出来的式子:C[i] = A[i]+A[i-1]+....+A[i-2^k+1];k代表i的二进制的最后连续0的个数,比如:对于1000和101000,k=3。

     节点和子节点之间是有关系的,这种关系就是 i=j+lowbit(j);lowbit 是 j 的最低位1所代表的数字,即二进制的高位1全部清空,只留下最低位的1。比如对于 1000(8的二进制) :1000=100+lowbit(100)=110+lowbit(110)=111+lowbit(111);

     其中, lowbit(j) = j&-j; 一个数加一个负号,根据补码,就是把这个数的二进制取反+1,如-10的二进制为-1010=0101+1=0110,然后用1010&0110,答案就是0010了。


    (1)当想要查询一个SUM(n)(求a[n]的和),可以依据如下算法即可:
step1: 令sum = 0,转第二步;
step2: 假如n <= 0,算法结束,返回sum值,否则sum = sum + Cn,转第三步;
step3: 令n = n – lowbit(n),转第二步。
可以看出,这个算法就是将这一个个区间的和全部加起来,为什么是效率是log(n)的呢?以下给出证明:
n = n – lowbit(n)这一步实际上等价于将n的二进制的最后一个1减去。而n的二进制里最多有log(n)个1,所以查询效率是log(n)的。比如,求0001~0110的和就直接c[0100]+c[0110]
    (2)那么修改呢,修改一个节点,必须修改其所有祖先,最坏情况下为修改第一个元素,最多有log(n)的祖先。所以修改算法如下(给某个结点i加上x):
step1: 当i > n时,算法结束,否则转第二步;
step2: Ci = Ci + x, i = i + lowbit(i)转第一步。
i = i +lowbit(i)这个过程实际上也只是一个把末尾1补为0的过程。
对于数组求和来说树状数组简直太快了!

    实现:

#include<iostream>
using namespace std;
int n,m,num[100001],t[200001],l,r;//n+1:数组的大小;num:原数组;t:树状数组 
int lowbit(int x)
{
    return x&(-x);
}

void change(int i,int p)//建立或修改建立树状数组,t[]的第i个数加p 
{
    while(i<=n)
    {
        t[i]+=p;
        i+=lowbit(i);
    }
    return;
}

int sum(int k)//求和;用t[]求num[1]~num[k]的和 
{
    int ans=0;
    while(k>0)
    {
        ans+=t[k];
        k-=lowbit(k);
    }
    return ans;
}

int ask(int l,int r)//求l-r区间和 
{
    return sum(r)-sum(l-1); 
}

int main()
{
    int i;
    cin>>n>>m;
    for(i=1;i<=n;i++) //n个数
    {
        cin>>num[i];
        change(i,num[i]);
    }
    for(i=1;i<=m;i++)
    {
        cin>>l>>r;
        cout<<ask(l,r)<<endl;
    }
    return 0;
}

参考:http://www.cnblogs.com/GeniusYang/p/5756975.html

          http://blog.csdn.net/int64ago/article/details/7429868

         


   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值