首先可以根据题目得到一堆环,我们把环分为偶数环、奇数环、单点,设偶数环的长度序列为
Seven,奇数环的长度序列为
Sodd,单点的数量为
K。
思考一下,给定一堆环的时候,我们应该根据什么策略填数。不妨设刚开始所有位置的数字都是
2,我们要选择
A0 个
2 变成
0,然后选择
A1 个
2 变成
1。
不妨认为,一个
0 会贡献
2,也就是向左和向右两个
mex 函数,一个
0 和一个
1 挨着可以贡献
1,也就是让
0 的贡献多
1,这样的位置对个数设为
X,两个
0 挨在一起可以贡献
−1,也就是产生了重复的贡献,如果一个单点有一个
0,也贡献
−1,这些位置的数量设为
Y。最终答案是
2A0+X−Y,也就是我们要最大化
X−Y。
由于我们是优先填写
A0,所以能想到计算出一个三元组
(X2,X1,Y) 表示,在某个填写
A0 的方案下,有
X2 个位置使得填写
1 后会让
X 增加
2,有
X1 个位置使得填写
1 后会让
X 增加
1,此时的
Y 等于三元组里面的
Y。
- 先填写在偶数环里面,并且隔着一个空格一个一个填 0。
- 然后填写奇数环,也是隔着空格一个一个填,如果一个奇数环的长度为 len,就填写 2len−1 个 0。先填写长度长的奇数环,再填写长度短的。
- 如果没有剩余的奇数环可以填了,就挑选那些存在相邻的空位的奇数环,把相邻空位的其中一个填写为 0。
- 填单点。
- 如果还剩余的有 0,就只能随便填了。
然后就可以根据上述的方案进行分讨了。
- 0≤A0≤2∑Seven。如果存在一个 S 的子序列 T,使得 A0=2∑T,那么三元组为 (A0,0,0)。如果不存在,则三元组为 (A0−1,2,0)。
- 2∑Seven<A0≤2∑Seven+2∑Sodd−∣Sodd∣。找到最小的 k 使得 Sodd 的前 k 项之和减去 k 再除以 2 大于等于 A0−2∑Seven,然后三元组为 (A0−k,2k,0)。从这里也可以反过来说明,为什么填奇数环的时候要先填写长度长的了。
- 2∑Seven+2∑Sodd−∣Sodd∣<A0≤2∑Seven+2∑Sodd+∣Sodd∣。设 s=A0−2∑Seven−2∑Sodd−∣Sodd∣ 表示要把多少个“相邻空位”填写为 0,三元组为 (A0−∣Sodd∣,2(∣Sodd∣−s),s)。
- 2∑Seven+2∑Sodd+∣Sodd∣<A≤2∑Seven+2∑Sodd+∣Sodd∣+K,每填写一个单点,Y 增加 1,所以三元组为 (2∑Seven+2∑Sodd−∣Sodd∣,0,A0−2∑Seven−2∑Sodd+∣Sodd∣)。
- 2∑Seven+2∑Sodd+∣Sodd∣+K<A。此时三元组为 (N−A0,0,N−2(N−A0))。
除了第一条,其他的三元组都可以线性预处理,至于第一条,不难发现这是一个背包问题,由于序列的元素大小之和为
O(n),不难
O(nn) 计算。