像潮落潮涌,送我奔向自由。|

寂静的海底

园龄:3年2个月粉丝:57关注:15

AGC028E High Elements 解题报告

神仙题。

称原序列 SP(S) 表示 S 的前缀最值序列,Q(S)=SP(S)A 表示分到部分 0 的序列,B 表示部分 1Di 表示 i 分到 0 或是 1(即答案)。

因为要求字典序最小的序列,考虑从前往后依次尝试每个位置能否填 0,若能填 0 就填 0,否则填 1,我们将问题转化为判定 某个填好了前半部分的序列是否存在 一种方式填后半部分使得最终两侧人数相同。

有很多状态较复杂的做法,例如记录或预处理 fi,m1,m2,dif 表示从第 i+1 个位置开始填,前 i 位,两侧的最值分别是 m1,m2,两侧核心人物数量的差为 dif 的情况,能否填完后半部分,这做法的复杂度是 O(n4),又因为观察到原序列目前的前缀最值一定是 AB 的最值,可以记录 fi,0/1,m,dif 表示前缀最值在 A/B,另一个序列的最值是 m,目前两侧的差为 dif 能否达到答案,复杂度 O(n3)

很难优化掉状态了:对于一侧最值的记录几乎无法省去。

考虑寻找一些性质——因为要处理的是两侧的最值个数的差,继续深究这个差的性质。

原序列的最值无论分到哪个序列都会成为前缀最值,而其它值好像总是可以通过调整使得它不为前缀最值。

定理:对于一种对剩下部分的某种划分,总是存在一种对应的划分方案,使得 AB 中的恰好一者的贡献全部由 P(S) 中的元素贡献,且对差值的贡献相同。

证明

对于任意一个元素 uQ(S),如果其为某个序列的前缀最大值,将其放到另一个序列中,其一定不是前缀最大值,因为原序列中比它大的元素被分到了另一侧,如果将其移动至这一侧就不可能是前缀最大值,同时因为它不是前缀最大值,也不会影响后面的元素。

所以如果两边都存在一个元素 u,vQ(S),且 uP(A),vQ(B),那么将 u 放入 B 中,v 放入 A 中,二者的差值一定都不会改变,进行这样的操作会使得两边的 uQ(S),uP(A),P(B) 的数量减少 1

所以不断进行这样的调整,一定可以将任意一种两侧都存在非原序列的序列最值的最值填充方案变成一种与之对应的只有一侧存在非原序列最值的最值。

即 对于一个 uP(A),vP(B):u,vQ(S) 的划分方案,不断进行 uB,vA,最终可以得到一个 uP(A):uQ(S)uP(B):uQ(S) 的划分方案。

现在我们可以用 所有 (某一个子序列不存在 Q(S) 中的元素产生贡献的列)的所有划分方案 的可行性,来代表 所有划分方案的可行性。


我们现在只用考虑某一侧的非原序列最值元素的贡献,不妨为 B,以及原序列最值的贡献,并钦定 A 中非最值元素 不会成为前缀最值。

又因为我们前面的理论,这个钦定是不必要的:因为它是非最值元素但成为了最值,我们可以把它挪到另一个序列 B 中,因为 B 中一定有比它大的数,所以它不会成为前缀最值。

在知道了这些结论后,接下来我们来考虑如何求:是否存在一组(对于某个已经填好的前缀 i 的) 后续填法(满足 B 中非最值元素的贡献,以及 A,B 中最值元素的贡献):

目前 A 序列的最值个数为 cA,cB 同理,A 中受最值元素的贡献是 PSAB 中受最值元素的贡献是 PSB,非最值元素为 QSB

那么我们要选取是否存在 cA+PSA=cB+PSB+QSB

因为 PSA+PSB 是一个定值(i 之后剩下最值个数),PSB 多选一个,PSA 就会少选一个,最值个数的差会改变 2

将上面的式子移项后可以得到 cAcB+V=2PSB+QSB

现在式子左边的都是定值了,我们要求的就是式子右边的仅和 B 相关的值,是否存在一种合法的子序列与之对应? 即要寻找一个 B 中产生贡献的最值的(上升)序列,原序列的最值 P(S) 中的元素的贡献为 2Q(S) 中的贡献为 1

因为可以将 B 中产生贡献的元素放到 A 中不再对上式的右半边产生贡献 ,所以如果值 2x+y(x,y>0) 可以被达到,那么值 2(x1)+y 一定都可以被达到,所以我们直接分奇偶维护最大值,查询能否达到某个值就是查询相同的奇偶性能达到最值。

fp,0/1 表示选择一个 p 开头的一个子序列的最大奇偶权值,那么它可以由 fq,0/1(ap<aq,p<q) 转移而来,转移类似最长上升子序列,可以用线段树或者树状数组维护。

:注意到上面这个式子是与 A 完全无关的,B 中最值的个数决定了 A 剩下的最值个数,B 中的其它元素与 A 没有影响。


在求出了 f 最值数组后,可以直接从前往后尝试每位能否填 0,求出字典序最小的数组,时间复杂度 O(nlogn)

回顾本题的推理过程,我们将序列分成两个序列这种较难处理的划分问题,通过分析将“所有答案的可行性”,使用“一侧不存在非最值元素贡献的答案的可行性”代表,然后再转化为“一侧不管非最值元素贡献的答案的可行性”,这样就把问题处理成了只需要选取一边子序列的贡献的问题了。

代码,为了使代码更加可读,把使用的类 seg 放在了代码的最后,这里是原提交记录。

posted @   寂静的海底  阅读(7)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起