树状数组概述

一些懒人由于觉得线段树难写的一逼,于是发明了树状数组。于是大佬们拿它去卡常。啥树套树的你套个树状数组,常数就小了下来,就快了好几倍。苦逼写线段树的同学还过不去了。

所以本着不卡别人也不被别人卡的思想,我们来学习一波树状数组。首先树状数组比线段树优秀的一点就是它的空间就小一半。我们只用开一个大小为n的数组,存的样子大概像这样:

这里写图片描述

什么意思呢?看到这个树形结构了么?

不好说明,举个例子:2号点存1-2的和;8号点存1-8的和;10号点存9-10的和;13号点存13-13的和;5号点存5-5的和。

然后我们就可以做到(单点修改,区间求和

我们来看一道题:P3374 【模板】树状数组 1

我们再引入一个概念: lowbit(x)=x l o w b i t ( x ) = x 的2的最大次幂。举个例子: lowbit(6)=2(6=23);lowbit(12)=4(12=43) l o w b i t ( 6 ) = 2 ( 6 = 2 ∗ 3 ) ; l o w b i t ( 12 ) = 4 ( 12 = 4 ∗ 3 )

然后我们就可以 logn l o g n 求前缀和了,查询时每次 lowbit(x) − l o w b i t ( x ) ,然后把那一个位置里的和加入 ans a n s 里。再举个例子,求7的前缀和:

767lowbit(7)46lowbit(6)04lowbit(4) 7 — — 6 ( 7 − l o w b i t ( 7 ) ) — — 4 ( 6 − l o w b i t ( 6 ) ) — — 0 ( 4 − l o w b i t ( 4 ) )
到0就结束。

从图里可以发现,我们正好把每个7前面的数都加了一遍。原理就是 lowbit(x) l o w b i t ( x ) 其实表示 x x 的管理范围。

然后考虑修改:修改时每次+lowbit(x),然后修改那一位置的值,我们就可以把所有实际管理 x x 的格子修改掉了。可以自己手动模拟一下,我就不举例子了。

然后前缀和相减,我们很容易可以过这道题。

接着我们在来看一道题:P3368 【模板】树状数组 2

诶,这道题要求我们(区间修改,单点查询)。

看似刚刚那种方法已经无解了,显然无法区间修改,我们每一次单点修改复杂度就是logn的,要是一段区间的话岂不是coldcold。那我们要想个办法把区间修改变为单点修改。于是很容易会想到差分。然后我们很惊奇地发现查询操作也很简单了。考虑我们以前差分后统计答案的方法,其实就是这个点前面的前缀和。这不是可以用树状数组轻松解决么?

举个例子:[3,6] +2,3号点+2,7号点-2。

查询4号点,求四号点前缀和。

用我们刚刚那种方法维护数组即可。

我们树状数组就讲完了,是不是很简单呢,时间上吊打线段树。

诶,不对啊,你还没讲 lowbit l o w b i t 怎么求。

啪!!!

哦~

其实你可以脑补出一种方法,据说考场上各路大佬现推公式都可以求。只要时间控制在 O(1) O ( 1 ) 即可。这里提供一种简单方法:

lowbit(x)= (-x)&x;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值