【问题标题】:What does "x += x & (-x)" mean?“x += x & (-x)”是什么意思?
【发布时间】:2020-03-18 13:51:39
【问题描述】:

我发现很多人使用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;
}

【问题讨论】:

  • 这是一些位技巧,但我太无聊了,无法自己解决。您应该能够通过尝试测试 m 的各种值并查看结果得到什么来解决这个问题,重复使用不同的 m 值直到您看到一个模式。
  • 你知道int 是如何用二进制表示的吗? m-m 的表示有什么区别? &amp; 导致只有他们两个都有的 1 位。
  • 我知道m-m&amp; 中的每一个,但我不知道我能从等式中得到什么。正如@SamVarshavchik 所说,我认为我应该尝试各种测试用例。谢谢大家!

标签: c++ algorithm bitwise-operators segment-tree binary-indexed-tree


【解决方案1】:

注意:此答案(与方法本身一样)假设有符号整数以two's complement 形式表示。

表达式x &amp; -x 是一种快速 - 但不可否认 - 获取 x最低 设置位表示的值的方法(当所有其他位很清楚)。这有时被称为位的权重,在数值上等于 2 的位位置的幂(其中最低有效位是位置 0)。

该方法依赖于这样一个事实:x 和 @ 的二进制 (2s-comp) 表示中只能设置一个 单个位 987654327@ - 这实际上是x 中设置的最低意义位。

Quora 上有很多关于其工作原理的很好的解释,并附有许多示例。

在您显示的updatequery 函数中,while 循环中增加/减少m 的量因此根据最小的位置加权 (原始)m 中的重要设置位。

请随时要求进一步澄清和/或解释(但我不希望复制/粘贴或解释太多我已链接的讨论)。

【讨论】:

    【解决方案2】:

    @Adrian 已经就表达式的含义给出了一个很好的答案,我将用一个简单的例子来补充它是如何工作的。

    假设我们的x 是一个 4 位数字(为简单起见)1100b。那么,

    1. x0000 1100b(它的最低设置位在位置 2 (索引从左开始在 0
    2. -x1111 0100b 作为 0000 1100b + 1111 0100b = 0b
    3. -x &amp; x 导致 0100b。唯一设置的位与x 中最右边的位在同一位置 - 在位置2

    【讨论】:

      【解决方案3】:

      另一种解释方式可以如下:

      X 是一个数字。 那么X&amp;-X代表the greatest power of 2 that divides X

      例子:

      1. X = 10,然后X&amp;-X 将给2
      2. X = 7,然后X&amp;-X 将给1
      3. X = 4,然后X&amp;-X 将给4

      【讨论】:

        【解决方案4】:

        在二进制索引树 (Fenwick_tree) 中,这些操作是更新和查询树。要查询树,您可以通过重置它最右边的设置位来查找元素的父级。要更新树,您需要向当前索引添加最低有效位以查找所有要更新的元素。

        【讨论】: