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子串的中间的那个/能够找出的最长子序列长度为
即可以利用预处理的信息,在$O(1)$的时间复杂度内计算出选择某个/时的答案。
并且可以通过二分 $pos_i$ 来得到需要枚举的 $i$ 的范围。
但是这样还是需要枚举 $[L,R]$ 内的所有/,如果/很多就寄了。
观察上式可以发现,随着 $posi$ 增大,$left1{posi}-left1_L$ 单调递增,$right2{pos_i}-right2_R$ 单调递减。$\min{增函数,减函数}$ 一定是一个开口向下的单峰函数,所以可以使用三分来确定最佳的 $pos_i$。
Code
1 |
|