QOJ # 5150. Alternating Algorithm

发布时间 2023-10-11 08:29:03作者: 275307894a

题面传送门

首先显然不能直接去维护这个操作,我们需要找到一些转化,将这个操作次数转化成一些值的最大值/最小值。

先离散成 \([0,n]\) 的排列。考虑每个 \(0\leq i < n\),将 \([0,i]\) 标记成 \(0\)\([i+1,n]\) 标记成 \(1\),记将标记后的序列排好序的次数为 \(g_i\),则最后答案为所有 \(g_i\) 的最大值。

先考虑一个只有 \(0/1\) 的序列排序怎么做。显然只需要考虑一个数,不妨考虑 \(0\)。因为 \(0\) 之间的相对顺序不会变,所以从前往后考虑每个 \(0\)。计算当前 \(0\) 移到最终位置的时间。但是这样不太对,因为前面的 \(0\) 可能会把后面的 \(0\) 挡住,这时从左往右依次考虑每个 \(0\) 与其之前 \(0\) 移到位的时间,如果前一个 \(0\) 移到位的时间大于后一个,则后一个会被前一个挡住,移到位的时间是前一个的时间 \(+1\),具体的,\(t_i=\max(t_{i-1}+1,t_i)\),这样可以 \(O(n)\) 算一次。

从小到大扫描线,则总修改次数是 \(O(n)\) 的,用线段树维护这个类似 ddp 的过程,时间复杂度 \(O(n\log n)\)

submission