树状数组
lowbit(子节点的父节点的位置差距,即下标对应的管理区间范围)
求解lowbit方法一:理解树状数组长度为2^k+2^n*y 0<=k<logn(以2为底) n<k,类似于快速幂加速计算。
为了方便理解,我们从k=0开始递推,那我们可以将(2^k次)视为一个不断增长的周期,即k+1更新周期长度,所以2^k的区间长度=2^k
至于2^k<x<2^k+1都可以视为(2^k)周期的映射,即x管理的区间为x-2^k对应的长度.
由此可以得出递推方程:lowbit[x]=lowbit[x-2^k],x!=2^k 所以我们只需要维护K就可以求出lowbit数组!
代码:
def lowbit(a):
k = -1
n = len(a)
lowbit = [0] * n
for i in range(1, n):
if i == 2 ** (k + 1):
k += 1
lowbit[0] = i
lowbit[i] = lowbit[i - 2 ** k]
#进一步思考:
#如果我们不从递推开始,而是想要直接求解lowbit(x),可以先定义lowbit(2^k)=2^k.
#当x!=2^k的时候,我们不知道x在2^k周期中的位置管理区间长度.
#当x==2^k的时候,我们知道了x在2^k周期中的位置管理区间长度.
#每一步得到x=x-2^logx(以2为底,下取整),当x=2^logx的时候,x就是管理区间的长度
#其实我们每一步操作都是在寻找x在2^k周期中位置,并不断缩小k,也就是周期大小。
#我们要寻找到解就是最小x==2^k,那还有没有更快的方法?
#既然周期是2^k,我们的下标却是十进制,相当于10^k一个周期,处理这样的周期问题,完全可以将下标转换为二进制.
#按照我们上面的求解lowbit(x)可以发现,二进制中1代表一个周期,我们要寻找的就是二进制最低位的1,也就是x=2^k.
#这就是我们熟知的求解lowbit(x)的方法.
代码:
def lowbit(x):
return x & -x