树状数组的详细解析

目录

1.为什么学习树状数组: 

2.简介lowbit()

3.树状数组的精髓(!!!!重点掌握)


1.为什么学习树状数组: 

1.简介:对于我的认知我认为树状数组是解决一些区间问题和单点问题的工具,首先树状数组从名字上来看是将数组变成了一个树的结构,在这颗树上进行着区间和单点的某一些操作。

   2.作用:此篇给出的树状数组的作用类似于前缀和。只不过和前缀和相比他提高了时间的  复杂度。

首先:前缀和是O(n)级别的,而树状数组是O(log(n))级别的。提高了时间的复杂度。其次:巧妙地利用了lowbit的属性,去降低了复杂度,而且把前缀和的各个位置遍历的极端位置给舍去了

2.简介lowbit()

 如果读者对于位运算不知道的很详细的话,不用去深究;

lowbit:

1.作用是返回该数字在二进制下的第一位1和后面的0组成的数字

例如:

lowbit(1) 1的二进制是 1 那么结果就为1

lowbit(2) 2的二进制是10那么返回结果是10这二进制组成的十进制数字2

lowbit(3) 3的二进制是11根据定义他返回的就是第一位1和后面的0组成的数字1

那么如果二进制是101110000 返回的是10000这四位在二进制下构成的十进制

2.上代码:(代码记过就可以短而精悍

int lowbit(int x)
{
    return x & (-x);
}

3.树状数组的精髓(!!!!重点掌握)

1.如果我们求一个区间(l,r)的和;

    一.我们会想到可以从l加到r呀。问题400ms的时间TLE是肯定的

    二.前缀和,非常完美可是前缀和还是可能超时(在数据很大的时候)。

    三.线段树,高级的数据结构,代码很冗长,但是学会他树状数组问题可以利用他解决

    四.树状数组,简洁和快。

2.树状数组的思想来源:(数字是这个数组的下标)

    1.我们来想如果有以下的几个数组。

    我们要求某个区间的和我们会怎么想?

   

   那么我们会这样子两两相加,这样子我们节省了一个一个判断的一半的时间

 那么我再一直相加变成这样子

那且不是更快。乍眼一看这不是是跟树差不多,可能把这个命名为树状数组!

    2.那么开算吧

     我们算一下几组:

      (l=1,r=1)=[1];

        (l=1,r=2)   =[1+2]

        (l=1,r=3)   =[1+2]+[3]

        (l=1,r=4)   =[1+2+3+4]

        (l=1,r=5)   =[1+2+3+4]+[5]

        (l=1,r=6)   =[1+2+3+4]+[5+6]

        (l=1,r=7)   =[1+2+3+4]+[5+6]+[7]

        (l=1,r=8)   =[1+2+3+4+5+6+7+8]

         呀!呀!呀!

         你可能有疑问问我:你咋不算(l=5,r=6)呢?

     1.我难道还要单独存吗,肯定不是,我在利用前缀和呀((l=5,r=6)= (l=1,r=6)-(l=1,r=4)

     2.仔细看有些东西压根用不到呀,如果存前缀和的话!

     

    观察我给出的几组样例每一行的偶数个都没有用呀,没用这不是占地方!删了!删了!

 删完这样子了。那这样子删完接下来咋办呢,lowbit你教我了咋搞?

看图

我把每个数组的二进制代码和lowbit值写了出来你会发现lowbit(x)对应右边的第几层

接着看

1+lowbit(1)=2//第二层
2+lowbit(2)=4//第三层

4+lowbit(4)=8//第四层

他会递层增加这样子我们加每一层就可

利用这个代码可以更新和赋值

void update(int x, int d) {   //修改元素a[x],  a[x] = a[x] + d
    while(x <= N) {
        tree[x] += d;
        x += lowbit(x);
    }
}

那么为什么会用这个呢

那得看查询了

int sum(int x) {          //返回前缀和sum = a[1] + a[2] +... + a[x]
    int ans = 0;
    while(x > 0){
        ans += tree[x];
        x -= lowbit(x);
    }
    return ans;
}

比如查询7吧

那么ans+=t[7]

7变成了6

ans+=t[6]

6变成了4

ans+=t[4]

4变成了0

也逐层的减少

重要的是理解图片即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值