有意思的树状数组

本文介绍了树状数组的基本概念,包括其逻辑结构以及如何用它高效地实现元素修改和子数列连续和的计算,通过示例展示了如何在O(logn)时间内求前n项和,低位操作在算法中的关键作用。
摘要由CSDN通过智能技术生成

树状数组本质上就是一个一维数组,那么我们为什么说它是树状,原因就在于其逻辑结构。树状数组主要实现两个功能:一是对某个元素的修改,二是求子数列连续和。

比如现在有这样的一列数a[1]~a[16]:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16。我们开辟一个树状数组tr[N],用来辅助求出数组a的前n项和。最朴素求前n项和的方法就是依次遍历a[i] += a[i-1],时间复杂度是O(n),我们利用树状数组便可以在O(logn)的时间复杂度求出a的前n项和。

树状数组的存储方式(第几级指的是该数二进制形式从右往左数第一个1是第几位   比如001:第一级;010:第二级……):比如现在我们读入a[1]这个数字,也就是1,毫无疑问此时tr[1]也应当存的是1,(树状数组与一般数组存储的不同之处:)此时tr[1](第一级)  tr[2](第二级)  tr[4](第三级)  tr[8](第四级)  tr[16](第五级)这些数也存下1这个数字。接着我们读入2这个数字,此时tr[2]更新为1+2=3,tr[4](第三级) tr[8](第四级) tr[16](第五级)也跟着更新,当读入3这个数字的时候,毫无疑问,这个时候跟tr[1] tr[2] 已经没有关系了,只需要更新tr[3]=3 tr[4]=6 tr[8]=6 tr[16]=6。依次类推。

int lowbit(int x)
{
    return x&-x;
}
修改某个元素
void add(int x,int v)
{
    for(int i = x; i <= n; i += lowbit(i);
     tr[x] += v;
}

子数列连续和
int query(int x)
{
    int res = 0;
    for(int i = x; i ; i -= lowbit(i))
        res += tr[i];
    return res;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值