[AGC007B] Construct Sequences
[AGC007B] Construct Sequences
先满足 \(a\) 单增,\(b\) 单减,构造一个 \(a = \{ N, 2N, \dots, nN \}\),\(b = \{ nN, \dots, 2N, 1N \}\),然后大家都在同一起跑线上。这里 \(N = 2\times 10^4 + 5\),是为了保证答案 \(a, b\) 元素大小关系的正确。这个 扩倍 卡了我很久!
首先要使 \(a_{p_1} + b_{p_1}\) 是唯一最小值,那就钦定 \(a_{p_1} + b_{p_1}\) 就等于 \(n + 1\),然后将其它 \(a_{p_i} + b_{p_i}\) 抬高。将 \(a\) 中 \(p_1\) 右侧的元素集体加一,\(b\) 中 \(p_1\) 左侧的元素集体加一,此时划归到大小为 \(n - 1\) 的子问题。
注意记录答案是在过程中进行的,才能保证 \(a + b\) 单增——所以你应该理解了,为什么在最初要进行扩倍。如果不扩倍,虽然 \(a, b\) 确实一直都是满足单调性的,但答案数组可不一定。幸运的是,\(a, b\) 中元素的偏移量最多为 \(n\),因此我给每个元素扩倍,实际上是让一个元素对应了一段 足够大的值域,让它在这个值域上进行变化,而值域是始终保持单调条件的。
这样做是 \(O(n^2)\) 的,可以用数据结构维护做到 \(O(n\log{n})\)。
但是听说还可以更给力一点,做到线性。
upd:我是憨憨!以下分别给出 \(\color{black}{\text{b}}\color{red}{\text{ottyl}}\) 和 \(\color{black}{\text{l}}\color{red}{\text{iuhangxin}}\) 的线性构造方式。
-
\(\color{black}{\text{b}}\color{red}{\text{ottyl}}\) 的构造:同样是扩倍,直接给 \(a_{p_i}\) 加上 \(i\) 不就可以了吗!!!
-
\(\color{black}{\text{l}}\color{red}{\text{iuhangxin}}\) 的构造:很不一样,但是一个有趣的调整法。
初始 \(a = \{ 1, 2, \dots, n \}\),\(b = \{ m - 1, m - 2, \dots, m - n \}\),其中 \(m = 10^9 - n\),考虑对 \(a\) 中的元素进行加操作,对 \(b\) 中的元素进行减操作。
然后将 \(a_{p_i}\) 加上 \(i\),这样 \(b, a + b\) 都满足了,但 \(a\) 不单增。
给 \(a_{x - 1} > a_x\) 的 \(a_x\) 加上 \(w = a_{x - 1} - a_x + 1\),同时给 \(b_x\) 减去 \(w\)。这时 \(b\) 又不单减了!
也就是说,在调整过程中,要同时考虑 \(a, b\) 的合法性。我们要给 \(a_x\) 加上一个数 \(w\),\(b_x\) 减去一个数 \(w\),最优策略下,取 \(w = \max(a_{x - 1} - a_{x} + 1, b_{x} - b_{x - 1} + 1, 0)\)。
这样 \(a + b\) 是不变的,且 \(a, b\) 时刻保证从开头到当前位置是合法的。当 \(a_n, b_n\) 确定下之后,整个序列都是合法的了。
确实是 \(\color{black}{\text{l}}\color{red}{\text{iuhangxin}}\) 能想出来的做法%%%
代码就没必要放了。