对给定数组的XOR查询

给定一个包含 n 个整数的数组,索引从 1->n。任务是执行 Q 次给定的查询,并在每次查询后打印数组总和

我们可以执行三种类型的操作:

  • 1 X:将 X 添加到数组中(其索引将为 n+1、n+2、...)
  • 2 Y:从数组中删除索引为 Y 的元素
  • 3 Z:对数组中的每个元素i,执行i^Z(i xor Z)

例子:

输入arr[] = {2, 3, 9, 5, 6, 6}, Q = 5

1 3

3 5

2 2

3 2

2 7

输出: 34 37 31 27 23

说明

1 3 -> arr[] = {2, 3, 9, 5, 6, 6, 3} -> 总和 = 34

3 5 -> arr[] = {7, 6, 12, 0, 3, 3, 6} -> sum = 37

2 2 -> arr[] = {7, 12, 0, 3, 3, 6} -> sum = 31

3 2 -> arr[] = {5, 14, 2, 1, 1, 4} -> sum = 27

2 7 -> arr[] = {5, 14, 2, 1, 1} -> sum = 23

P/S:我正在尝试使用 Segment Tree 解决问题,但我无法使用 XOR 运算符更新树。有没有其他方法可以解决这个问题?我试图在 O(n.logn) 中解决它

回答

假设您的数字不超过一些标准常数,如 2 32或 2 64,我们可以在恒定时间内通过分别计算位来做到这一点。

您将需要:

  1. 记住数组中有多少个数字
  2. 记住二进制定位系统中每个位置有多少点亮位。

所以这是您的示例,扩展为位,最不重要的位于顶部:

2  3  9  5  6  6  3 | sum
-------------------------
0  1  1  1  0  0  1 | 4
1  1  0  0  1  1  1 | 5
0  0  0  1  1  1  0 | 3
0  0  1  0  0  0  0 | 1

现在,这意味着有

  • 4 “第一个”位亮起
  • 5 “第二”位亮起
  • 3 “第三”位点亮并且
  • 1 “第四”位亮起。
  • 数字的数量是7
  • 这些数字的总和是 34

我们现在将这个与5,它是0101二进制的,所以现在将有

  • 7 - 4 = 3 “第一个”位亮起
  • 5 “第二”位亮起
  • 7 - 3 = 4 “第三”位亮起
  • 1 “第四”位亮起

如果我们总结一下,我们得到3 * 2^0 + 5 * 2^1 + 4 * 2^2 + 1 * 2^3 = 37(现在^我的意思是取幂而不是异或)。

所以这就是你每次弹出 xor 操作时所做的。添加和删​​除数字是很容易的部分,因为您会检查它们的位并相应地调整i数组中点亮的“ -th”位的计数。


以上是对给定数组的XOR查询的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>