CF1621F Strange Instructions 题解

给出一个 01 串 \(s\),每次可以进行以下操作:

  1. \(00 \to 0\),收益为 \(a\)
  2. \(11 \to 1\),收益为 \(b\)
  3. 删除一个 \(0\),代价为 \(c\)

要求相邻两次操作的型号的奇偶性必须不同,你可以进行任意多次操作,问最后的收益最大值。

\(|s| \le 10^5,1 \le a, b, c \le 10^9\)


  贪心

  因为 2 是每两次就必须的操作,因此我们考虑之后每次操作后能否继续进行 2 操作,定义势能为字符串中连续的 1 的个数,也就是如果一直进行 2 操作的最多次数,同时也可以发现,操作 \(2\) 具体的位置是不重要的。

  那么对于操作 3,如果删除的 \(0\) 是一个孤立的 \(0\)(左右都是 \(1\) 或者边界),并且 \(0\) 旁边都有 \(1\),这样势能就会增加 \(1\),我们以 \(c\) 的代价使得操作 \(2\) 能够进行次数 + 1,因此操作 3 内部的顺序就是 尽量删除中间的孤立 \(0\),最后删除边角的孤立 \(0\)

  注意到 1 、3 操作都是使得 \(0\) 的个数 \(-1\),区别仅在于当这个删除的 \(0\) 是一个孤立的 \(0\) 的时候贡献为 \(-c\),否则为 \(+a\),因此我们只有在删除孤立的 \(0\) 的时候才会使用操作 \(3\),否则就使用操作 \(1\),除非某些情况下必须使用 \(3\) 才能继续进行操作 \(2\),于是 1 、3 操作的顺序确定了下来。

  现在考虑操作 \(1\) 之间的顺序,假如现在有若干 0(非孤立的 0),我们一定是先从中间的最短一段 \(0\) 下手,这样才会有更多机会创造孤立 \(0\),进而使得操作 2 继续进行。


  整理一下:

  如果我们要进行 \(2\) 操作:

  • 能动就动。
  • 否则游戏终止。

  如果我们要进行 \(1\) 操作:

  • 如果当前的势能已经到了 \(0\),现在就属于游戏进行的生死存亡时刻:
    • 不玩了,最后捞一笔钱,如果能进行 1 操作,则进行,然后结束游戏。
    • 继续玩,删除一个中间的孤立 \(0\),游戏继续。
  • 势能 \(>0\),现在不急,可以水时长,同时进行一些储备,于是肯定是优先考虑 \(1\) 操作:
    • 如果还有 \(0\) 的段,那么我们从中间的段中挑一个最短的进行操作 \(1\),这样有利于后面继续操作。
    • 中间没有的话就从边上的一段进行操作 \(1\)
    • 实在不行,只能使用操作 \(3\),删除中间孤立 \(0\),顺便使得势能 \(+ 1\)
    • 还是实在不行就从边上进行操作 \(3\),但是势能不变。
    • 玩不下去了,终止游戏。

  选择最短的段可以预先排序然后维护栈解决,时间复杂度 \(\mathcal O(n \log n)\)

  代码

  

posted @ 2022-01-04 17:19  Werner_Yin  阅读(76)  评论(4编辑  收藏  举报