树状数组的一些认识
2010-08-05 23:32
190 查看
int lowbit(int x){ return x&(x^(x–1));
}
这个函数的值为2的k次方。形象的就是把二进制的最后一个1和后面的0都拿出来。
有了形象的感知,函数也就很好理解了。要是把最后一个1和零拿出来,我们先x-1,原先a100...0就变成了a011...1.a异或a为0,所以二进制就变为了000111...1。
构造线段树的规则的理解,可以从二进制中1的个数来理解。百度百科中,求和和修改的解释是不错的。
当想要查询一个SUM(n)(求a
的和),可以依据如下算法即可:
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)的。
那么修改呢,修改一个节点,必须修改其所有祖先,最坏情况下为修改第一个元素,最多有log(n)的祖先。
所以修改算法如下(给某个结点i加上x):
step1: 当i > n时,算法结束,否则转第二步;
step2: Ci = Ci + x, i = i + lowbit(i)转第一步。
i = i +lowbit(i)
这个过程实际上也只是一个把末尾1补为0的过程。
}
这个函数的值为2的k次方。形象的就是把二进制的最后一个1和后面的0都拿出来。
有了形象的感知,函数也就很好理解了。要是把最后一个1和零拿出来,我们先x-1,原先a100...0就变成了a011...1.a异或a为0,所以二进制就变为了000111...1。
构造线段树的规则的理解,可以从二进制中1的个数来理解。百度百科中,求和和修改的解释是不错的。
当想要查询一个SUM(n)(求a
的和),可以依据如下算法即可:
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)的。
那么修改呢,修改一个节点,必须修改其所有祖先,最坏情况下为修改第一个元素,最多有log(n)的祖先。
所以修改算法如下(给某个结点i加上x):
step1: 当i > n时,算法结束,否则转第二步;
step2: Ci = Ci + x, i = i + lowbit(i)转第一步。
i = i +lowbit(i)
这个过程实际上也只是一个把末尾1补为0的过程。
相关文章推荐
- C语言循环数组做FIFO队列--一些认识
- 【转】树状数组求区间和的一些常见模型
- C语言循环数组做FIFO队列--一些认识
- 树状数组详介绍-想深刻认识树状数组,进来吧
- 从头认识C—指针和数组的一些浅谈
- 【转载】树状数组求区间和的一些常见模型
- js中关于数组复制的一些认识(感谢IT民工和见Q,如见人的指导)
- HashMap中关于数组和链表的一些认识
- 树状数组求区间和的一些常见模型
- HashMap中关于数组和链表的一些认识
- 树状数组求区间和的一些常见模型
- 树状数组求区间和的一些常见模型
- 线段树和树状数组的认识与总结
- 网上收集的一些树状数组文章
- 【数据结构之树状数组】从零认识树状数组
- C语言循环数组做FIFO队列--一些认识
- ACM集训——POJ2352---一维树状数组的应用
- 树状数组应用之——求逆序对
- hdu 3874 树状数组 离线处理
- 关于GCD的一些认识