加载中...

cf div2 1091 D (01串的区间翻转与差分)

D. Flip the Bit (Hard Version)

Q:给定一个 01 串,并给定若干位置作为 01 串的多个 pivot(分界点),其中每个 pivot 位置上的数字均相同(0 或 1,设为 x)。每次操作可以选择 01 串的某个子区间 \([l, r]\),要求:

  • 该区间必须至少包含一个 pivot
  • 将该区间内的所有字符翻转(01 互换)

求将该 01 串变成全 x 的最少操作数。

对于 01 串的区间翻转操作,有一个比较经典的 trick:考虑所有位置的异或差分(\(b_{i} = s_{i} \oplus s_{i+1}\)),一次区间翻转操作只会改变某两个 \(b_{i}\) 具体地,对区间 \([l, r]\) 进行翻转,只会改变 \(b_{l-1}\)\(b_{r}\)。这很显然,不证明了。

对于本题,目标是让所有字符变成 x。我们不妨在 01 串的首尾均添加一个 x($s_{0} = s_{n+1} = $ x),然后考虑改造后的 01 串的异或差分,那么目标就等价于让每一项异或差分均为 0。如果没有 “操作区间必须包含至少一个 pivot” 这条限制,那么显然每次操作可以贪心地匹配两个 \(b_{i} = 1\),让它们均变为 0,这样是最优的。而添加了这条限制后,相当于将所有的 \(b_{i}\) 划分成了多个部分,每次只能选择两个不同部分的 \(b_{i}\) 并对它们作翻转,那么此时的贪心策略也非常经典:给定若干堆不同数量的石子,每次可以分别拿取两个不同堆中的一颗石子,也可以只拿取某一堆的一颗石子,求将石子全部拿完的最小操作数。容易发现两个问题是完全等价的,答案即为:

\[\max(\lceil \frac{总石子数量}{2} \rceil,最大堆石子数量) \]

特殊地,对于本题,由于 $s_{0} = s_{n+1} = $ x,连续 0 与连续 1 组成的段的数量一定是奇数,因此 \(b_{i}=1\) 的数量一定是偶数,所有区间翻转操作后不会剩下单个 \(b_{i}=1\) 的情况。

code

posted @ 2026-04-08 16:33  小橘奏  阅读(54)  评论(0)    收藏  举报