把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

UOJ #807. 【UR #25】装配序列

题面传送门

首先根据 Dliworth 定理,原问题等价于前缀 LIS。

考虑如何做到 \(O(n^2)\) 求出 LIS 的变化点(显然这只有 \(n\) 个)。按照值从小到大考虑,记 \(f_{i,j}\) 表示考虑到第 \(i\) 个值,长度为 \(j\) 的 LIS 最早在哪个前缀处出现,转移只需要 two-pointers 一遍就能更新。

这个转移的实质是:考虑这个值在原序列中出现的位置 \(p\),从大到小,依次找到 \(f_i\) 中第一个 \(\geq p\) 的点更新成 \(p\)。归纳一下可以说明,每种值的位置在 \(f\) 中出现的是一个前缀。也即,若 \(p+kn\) 出现了,\(p+(k-1)n\) 一定出现。

则我们可以改成记 \(c_i\) 表示第 \(i\) 个位置上的值出现了几次,然后考虑转移,假设当前值出现的位置是 \(x\),考虑 \(i=x+1,x+2,\dots n\),若 \(c_x<c_i\),则交换 \(c_x,c_i\)

\(c_x\) 加一后对 \(i=1,2,3,\dots x-1\) 做同样的操作。

容易发现 \(\sum c=n\),且 \(c_x\) 每次操作都会增加,因此总共只会更新 \(c_x\) \(O(\sqrt n)\) 次,用线段树找到这些位置即可做到 \(O(n\sqrt n\log n)\)然后在 ex_test 6 T 飞了

正确的做法是用 set 维护每种出现过的值以及出现的位置,然后查询的时候在每个 set 里面 lower_bound。这样的复杂度是 \(O(\sum \log siz_i)\),其中 \(siz_i\)\(c\) 的值为 \(i\) 的出现次数,要满足 \(\sum isiz_i\leq n\)。这个复杂度相当于 \(O(\sum\limits_{i}\sum\limits_{j}[siz_j>2^i])\leq O(\sum \limits_{i}\sqrt\frac{2n}{2^i})=O(\sqrt n)\),于是就可以通过了。

submission

posted @ 2024-07-02 14:52  275307894a  阅读(77)  评论(1编辑  收藏  举报
浏览器标题切换
浏览器标题切换end