我发现许多人使用x += x & -x
,x -= x & -x
解决间隔树问题。你能解释一下这个方程是什么意思吗?
void update(int m, int x) {
m++;
while (m < N) {
t[m] = t[m] + x;
m += m & -m;
}
}
int query(int m) {
int result= 0;
m++;
while (m > 0) {
result = result + t[m];
m -= m & -m;
}
return result;
}
答案 0 :(得分:7)
注意:此答案(如方法本身一样)假定有符号整数以two's complement形式表示。
表达式x & -x
是一种快速的-但公认的奥秘-一种获取x
中最低设置位表示的值的方法(当所有其他位都清除时)。有时称为比特的 weight ,在数值上等于2增大到比特位置的幂(其中最低有效比特是位置0
)。
该方法依赖于这样一个事实,即只能在两个x
的二进制(2s-comp)表示中设置 单个位 和-x
-这实际上是x
中最低有效位的设置位。
Quora上有许多示例,对此进行了很好的解释。
在您显示的update
和query
函数中,对m
循环中增加或减少while
的量进行了加权 根据(原始)m
中最低有效位的位置。
可以随时要求进一步的澄清和/或解释(但我不想复制/粘贴/释义过多的链接)。
答案 1 :(得分:1)
@Adrian已经对表达式的含义给出了很好的答案,我将通过一个简单的示例对其进行补充。
让我们考虑一下我们的x
是一个4位数字(为简单起见)1100b
。然后,
x
是0000 1100b
(其最低设置位在位置2
(索引从0
的左侧开始)-x
与1111 0100b
一样是0000 1100b + 1111 0100b = 0b
-x & x
产生0100b
。唯一的置位位置与x
中最右边的位置相同-位置2
。 答案 2 :(得分:1)
在二进制索引树(Fenwick_tree)中,这些操作正在更新和查询树。要查询树,您需要通过重置元素的最右边设置位来查找它的父元素。要更新Tree,您需要在当前索引中添加最低有效位,以查找所有要更新的元素。
答案 3 :(得分:0)
另一种解释方式如下:
让X
为数字。
然后X&-X
代表the greatest power of 2 that divides X
。
示例:
X = 10
,然后X&-X
将得到2
。X = 7
,然后X&-X
将得到1
。X = 4
,然后X&-X
将得到4
。答案 4 :(得分:-2)
int
中的AFAIK第一位是符号位(负数为1,正数为0)。
x & -x
运算的结果为x的正(绝对)值。
所以你在做什么:
1. x为正数时
a)x += x & -x
->您得到x+x
b)x -= x & -x
->您得到0
2. x为负数时
a)x += x & -x
->您得到0
b)x -= x & -x
->您得到x-x