AtCoder Beginner Contest 381-E
Problem
一个长度为奇数、最中间的那个字符是 /
、左边所有字符都是都是 1
、右边所有字符都是 2
的字符串被称为11/22 字符串。
更加严谨的定义:
当一个字符串 \(T\) 满足以下所有条件时,它被称为11/22 字符串:
- \(|T|\) 是奇数。这里, \(|T|\) 表示 \(T\) 的长度。
- 从第 \(1\) 到第\((\frac{|T|+1}{2} - 1)\) 个字符都是
1
。- 第 \((\frac{|T|+1}{2})\) 个字符是
/
。- 从第 \((\frac{|T|+1}{2} + 1)\) 到第 \(|T|\) 的字符都是
2
。
例如,11/22
、111/222
和/
是 11/22 字符串,但1122
、1/222
、11/222
、22/11
和/2/2/211
则不是。
给定由1
、2
和/
组成的字符串 \(S\) ,\(|S|=N\)。有 \(Q\) 次询问:给定 \(L\) 和 \(R\),设 \(T\) 是 \(S\) 的从第 \(L\) 个字符到第 \(R\) 个字符组成的子串。请找出 \(T\) 的最长子序列使得该子序列是一个 11/22 字符串。如果不存在这样的子序列,则打印 "0"。
Constraints
- \(1 \leq N \leq 10^5\)
- \(1 \leq Q \leq 10^5\)
- \(S\) is a string of length \(N\) consisting of
1
,2
, and/
. - \(1 \leq L \leq R \leq N\)
- \(N\), \(Q\), \(L\), and \(R\) are integers.
Solution
考虑预处理出所有/
的位置,记作 \(pos_i\)。
使用前缀和后缀和计算“每一个字符之前有多少个1
”和“每一个字符之后有多少个2
”,分别记作 \(left1_i\) 和 \(right2_i\)。
对于每次询问,一个简单暴力的算法就是,枚举在该区间内的所有/
,并看看其左右分别有多少个1
和2
,则选择该/
作为11/22
子串的中间的那个/
能够找出的最长子序列长度为 \[
\begin{align}
ans_i=\min\{left1_{pos_i}-left1_{L},right2_{pos_i}-right2_{R}\} \quad L\le pos_i \le R
\end{align}
\] 即可以利用预处理的信息,在\(O(1)\)的时间复杂度内计算出选择某个/
时的答案。
并且可以通过二分 \(pos_i\) 来得到需要枚举的 \(i\) 的范围。
但是这样还是需要枚举 \([L,R]\) 内的所有/
,如果/
很多就寄了。
观察上式可以发现,随着 \(pos_i\) 增大,\(left1_{pos_i}-left1_L\) 单调递增,\(right2_{pos_i}-right2_R\) 单调递减。\(\min\{增函数,减函数\}\) 一定是一个开口向下的单峰函数,所以可以使用三分来确定最佳的 \(pos_i\)。
Code
1 |
|