Loading

数据恢复

https://xinyoudui.com/ac/contest/74500D24A000A6307D59EF/problem/43680

容易注意到该问题在 \(a_1 = n\) 时复杂度最优为 \(O(n \log n)\),所以可以不用思考线性做法。

首先考虑 \(a_1 = n\) 我们到底在干啥,实际上求的是后面 \(n - 1\) 的上升子序列个数,相当于我们是统计的清晰的数到底是哪些。

考虑将这个做法套用到限制更广的情况下,发现一个事情就是,对于 \(c_i = 0\) 的部分我仍然要满足这个上升的性质,不然也可以交换并且不改变前缀最大值,现在我们只需要考虑前缀最大值 \(a_i\) 的情况了。

不妨令 \(a_i\)\(a_{1 \sim i}\) 的前缀最大值,那么考虑如果它不清晰,哪些位置必须得是清晰的:则是对于每个 \(j > i\)\(a_j > a_{1 \sim i - 1}, a_j > a_{i + 1 \sim k}\)\(a_j < a_i\)\(k\)\(i\) 后面一个前缀最大值的位置,此时如果 \(a_j\) 是不清晰的,那么将 \(a_i, a_j\) 交换明显可以使得字典序更小,不难发现这便是充要条件。

根据这一条限制,可以得到如果前缀最大值 \(a_i\) 是不清晰的,那么它不会影响后面的前缀最大值 \(a_j\),因为显然前缀最大值都是依次递增的关系,因此我们得到,对于前缀最大值的决策,全部是完全独立的(因为你考虑一个位置固定必定比一个位置不固定自由度要小)。

考虑对于非前缀最大值可以时刻拿出一个上升子序列做一些手脚,也就是说,如果你目前的上升子序列集合为 \(S\),记录一下每个前缀最大值所被限制的数构成的集合包含于 \(S\) 的个数为 \(c\) 个,那么此时贡献可以乘上 \(2^c\),请注意我们这个过程是在值域上做的,因为如果按照下标做的话就离散了,化成值域就可以边 DP 边记录。

考虑将原本在序列上的 DP 也改成值域上,那么就是将下标和值翻转一下,仍然是那个 DP,你发现可以通过在 BIT 里先打标记后查询乘逆元简单的将这个系数还原出来,于是就做到 \(O(n \log n)\) 了。

posted @ 2026-01-20 17:24  Alexande  阅读(1)  评论(0)    收藏  举报