位操纵:更难掷硬币

Bit Manipulation: Harder Flipping Coins

本文关键字:硬币 操纵      更新时间:2023-10-16

最近,我从CodeChef看到了这个问题,标题为"翻硬币"(链接:FLIPCOINS)。

总而言之,有N个硬币,我们必须编写一个支持两个操作的程序。

  1. 在范围 [A,B] 中掷硬币
  2. 分别查找范围 [A、B] 中的磁头数。

当然,我们可以快速使用区段树(范围查询,使用延迟传播的范围更新)来解决这个问题。

然而,我遇到了另一个类似的问题,在一系列翻转(操作 1)之后,我们需要在翻转后输出硬币的结果排列(例如100101,其中 0 代表正面,1 代表反面)。

更具体地说,操作 2 从计算正面数量变为产生所有 N 个硬币的结果排列。此外,只有在完成所有翻转后才会调用新操作 2(即操作 2 是最后一个调用的,并且只调用一次)。

我可以知道如何解决这个问题吗?根据问题标签,它需要某种形式的位操作。

编辑

我尝试暴力破解所有查询,唉,它产生了超过时间限制。

打印出硬币的状态可以使用二进制索引树来完成:

  • 最初,所有值都0
  • 当我们需要[A, B]抛硬币时,我们将A递增1和 递减B + 11.
  • 硬币i的状态是i2的前缀和。

这是有效的,因为i处的前缀总和始终是在i处完成的翻转操作数。