『数据结构』树状数组
树状数组的问题模型:现在有一个这样的问题: 有一个数组(a),下标从(0)到(n-1),现在你要进行(w)次修改,(q)次查询。 (for) (example),(x=6),它的二进制为(110), 求负数的补码的简便方法: 先把这个数的二进制写出来,然后从右向左找到第一个(1),这个(1)不要动和这个(1)右边的二进制不变,左边的二进制依次取反,这样就求出的一个数的补码,说这个方法主要是让我们理解一个负数的补码在二进制上的特征,然后我们把这个负数对应的正数与该负数与运算一下,由于这个(1)的左边的二进制与正数的原码对应的部分是相反的,所以相与一定都为(0),由于这个(1)和这个(1)右边的二进制都是不变的,因此,相与后还是原来的样子, 所以,这个得出的结果就是(lowbit(x))的结果。 lowbit函数:int lowbit(x) { return x & -x; } 二进制的视角:一个数(n),假设(n=6),它的二进制为(110),我们把它表示成累加的形式(110=100+10),这样是可以的,那么我们要求前(6(110))项的和可以这样求: (∑i=16=(a[1]+a[2]+a[3]+a[4])+(a[5]+a[6])) 注意括号中的元素个数, (∑6i=1=(a[1]+a[2]+a[3]+a[4]+(a[5]+a[6])=) (∑6i=1=(a[1]+a[2]+a[3]+a[4])+c[6]) (∑i=16=(a[1]+a[2]+a[3]+a[4])+(a[5]+a[6])=) (∑i=16=(a[1]+a[2]+a[3]+a[4])+c[6];) 你可以把(c[6])去掉,就变成了 (∑4i=1=(a[1]+a[2]+a[3]+a[4])) (∑i=14=(a[1]+a[2]+a[3]+a[4])) 这个区间就靠右端点了, (∑4i=1=c[4]=c[6-lowbit(6)]) (∑i=14=c[4]=c[6-lowbit(6)])。 设计一种数据结构,需要的操作无非就是更改和查询, 查询这里说的查询是查询任一区间的和,由于区间和具有可加减性,所以转化为求前缀和; 修改修改某一位置上的元素的时间复杂度为(O(1)), 图片中已经把(c)数组的后缀和这个含义已经表达得很清楚了。 树状数组的代码实现对某个元素进行加法操作:void update(int x) { while(x<=n) { c[i]+=x; x+=lowbit(x); } } 查询前缀和:int sum(int x) { int res=0; while (x>0) { res+=c[x]; x-=lowbit(x); } return res; } 洛谷树状数组题: 【模板】树状数组 1:p3374 【模板】树状数组 2:p3368 中位数:p1168 逆序对:p1908 虔诚的墓主人:p2154 无尽的生命:p2448 推销员:p2672 上帝造题的七分钟:p4514 (编辑:淮北站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |