位操作:更难翻转硬币
Posted
技术标签:
【中文标题】位操作:更难翻转硬币【英文标题】:Bit Manipulation: Harder Flipping Coins 【发布时间】:2018-04-15 07:00:44 【问题描述】:最近,我从 CodeChef 看到了这个题为“Flipping Coins”的问题(链接:FLIPCOINS)。
总而言之,有 N 个硬币,我们必须编写一个支持两种操作的程序。
-
在 [A,B] 范围内抛硬币
分别查找范围 [A,B] 内的正面数。
当然,我们可以快速使用分段树(范围查询,使用惰性传播的范围更新)来解决这个问题。
但是,我遇到了另一个类似的问题,在一系列翻转后(操作 1),我们需要输出翻转后的硬币排列结果(例如 100101,其中 0 代表头部,1 代表尾部)。
更具体地说,操作 2 从计算正面数量变为产生所有 N 个硬币的结果排列。此外,新的操作 2 仅在 所有翻转完成后调用(即操作 2 是最后一个被调用的,并且只被调用一次)。 p>
我可以知道如何解决这个问题吗?根据问题标签,它需要某种形式的位操作。
编辑
我尝试对所有查询进行暴力破解,可惜,它产生了 Time Limit Exceeded。
【问题讨论】:
你好,你能告诉我们你自己的想法吗? 【参考方案1】:可以使用二进制索引树来打印硬币的状态:
最初所有值都是0
。
当我们需要抛硬币[A, B]
时,我们将A
增加1
和
将B + 1
递减1
。
硬币i
的状态是i
处的前缀和模2
。
之所以有效,是因为i
处的前缀总和始终是i
处完成的翻转操作数。
【讨论】:
如果只做增量和减量而没有范围求和,为什么还需要 BIT? 我们需要前缀和来确定每个硬币的状态。x
的前缀总和是直到 x
的所有元素的总和。
但是你只需要在最后执行一次(OP 说“即操作 2 是最后一个被调用的,并且只被调用一次”)。以上是关于位操作:更难翻转硬币的主要内容,如果未能解决你的问题,请参考以下文章