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

浙公网安备 33010602011771号