Loading

ABC408D 翻译+题解

题面汉化

问题陈述

给定一个长度为 \(N\) 的字符串 \(S\),仅由字符 '0''1' 组成。

你可以执行如下操作任意次(也可以不执行):

  • 选择一个整数 \(i\) 满足 \(1 \leq i \leq N\),将 \(S_i\)'0' 变为 '1',或从 '1' 变为 '0'

你的目标是让字符串中的 '1' 最多只形成一个连续区间。请计算为实现这一目标所需的最少操作次数。

更准确地说,你需要将 \(S\) 变为满足以下条件的形式,并求出所需的最小操作次数:

  • 存在一对整数 \((l, r)\) 满足 \(1 \leq l \leq r \leq N+1\)
  • 对于所有 \(1 \leq i \leq N\)\(S_i = \texttt{'1'}\) 当且仅当 \(l \leq i < r\)

保证总能通过有限次操作达成目标。

给定 \(T\) 组测试数据,请分别求解。

限制条件

  • \(1 \leq T \leq 2 \times 10^4\)
  • \(1 \leq N \leq 2 \times 10^5\)
  • \(S\) 是一个仅包含字符 '0''1' 的长度为 \(N\) 的字符串
  • 每个输入文件中,所有测试数据的 \(N\) 总和不超过 \(2 \times 10^5\)
  • \(T, N\) 均为整数

输入格式

输入由标准输入给出,格式如下:

\(T\)
\(\textrm{case}_1\)
\(\textrm{case}_2\)
\(\vdots\)
\(\textrm{case}_T\)

其中,第 \(i\) 组测试数据 case_i 的格式如下:

\(N\)
\(S\)

输出格式

输出 \(T\) 行。第 \(i\) 行(\(1 \leq i \leq T\))应输出第 \(i\) 组测试数据的答案。


题解

题意

选择一个区间 \([l, r)\),使得将该区间外的 \(1\) 变为 \(0\),区间内的 \(0\) 变为 \(1\) 所需要的翻转次数(代价)最少。

注意:因为我们不仅能把 \(1\) 变成 \(0\),同时也能把 \(0\) 变成 \(1\),因此不能只考虑保留最长的 \(1\) 串。我们也可以通过翻转 \(0\) 让两个 \(1\) 串合并。

思路

如果暴力枚举,复杂度为 \(O(N^2)\) 会超时。可以通过前缀和优化求区间代价的过程,但本质还是暴力枚举,依然需要优化。

\(c_0[i]\)\(s[i]\) 之前(包括 \(s[i]\) )的 \(0\) 的数量,\(c_1[i]\)\(s[i]\) 之前(包括 \(s[i]\) )的 \(1\) 的数量。总代价为:

\[\begin{align*} cost &= c_0[r]-c_0[l-1]+c_1[n]-c_1[r+1-1]+c_1[l-1]-c_1[1-1]\\ &= c_0[r]-c_0[l-1]+c_1[n]-c_1[r]+c_1[l-1]-c_1[0]\\ &= c_0[r]-c_1[r]-(c_0[l-1]-c_1[l-1])+c_1[n]-c_1[0] \end{align*} \]

令:

\[diff[x] = c_0[x]-c_1[x] \]

得:

\[cost = diff[r] - diff[l-1] + c_1[n]-c_1[0] \]

因为 \(c_1[n]\)\(c_1[0]\) 都是常数,此时将问题转化为:在数组 \(diff\) 上选择一个区间 \([l, r)\),使得 \(diff[r] - diff[l-1]\) 最大。使用双指针优化,在遍历每个 \(r\) 的同时维护最大的 \(diff[l-1]\) 即可将复杂度优化为 \(O(N)\)

最终代码

posted @ 2025-06-07 12:16  BaguetteShimada  阅读(25)  评论(0)    收藏  举报