APIO 2022

T2 游戏

\(1\) 开始编号。

\(L(i)\) 表示能走到 \(i\)\([1,k]\) 中最大的点。

\(R(i)\) 表示从 \(i\) 开始走能走到的 \([1,k]\) 中最小的点。

假设之前没有形成环,当前加入了一条边 \((u,v)\)

如果这时形成了环,那么环中必定含有边 \((u,v)\)

这相当于 \(L(u)\geq R(v)\)

当加入一条边 \((u,v)\) 时,会影响 \(v\) 能走到的点的 \(L\),会影响能走到 \(u\) 的点的 \(R\)

于是可以用 \(L(u)\) 去更新 \(v\) 能走到的点的 \(L\),用 \(R(v)\) 去更新能走到 \(u\) 的点的 \(R\)

如果暴力更新,复杂度为 \(O((n+m)m)\)

我们只需要判断是否有环,并不需要严格地维护 \(L\)\(R\),因此很多更新是没有必要的。

因为有环相当于 \(L(u)\geq R(v)\),因此 \(v\) 的线段必须在 \(u\) 的左边。

有这样一个性质:\(L(v)\geq L(u)\)\(R(u)\leq R(v)\)

可以根据这个性质更新 \(L(v)\)\(R(u)\)

画图后可以发现,只有当 \(v\)\(u\)\(u\) 的左侧相交时,或 \(v\)\(u\) 包含时才可能更新出环。

可以考虑把线段放到线段树上更新,且钦定区间只能是线段树的区间,可以证明,这样并不会影响答案的正确性。

这样,每条线段最多只会更新 \(O(\log k)\) 次,因此总复杂度为 \(O((n+m)\log k)\)

T3 排列

将序列分成很多段上升序列,其中前面的上升序列中的所有元素严格大于后面的上升序列的所有元素。

那么需要满足

\[\sum_{i}2^{x_i}-1=k-1 \]

于是得到了一个 \(O(\log^2 k)\) 的构造。

假设 \(n=\log_2k\),先构造一个长度为 \(n\) 的上升序列,然后再对 \(k-2^n\) 二进制分解,可以得到 \(O(2\log k)\) 的构造。

再考虑优化,如果二进制分解后有两个连续的 \(1\),且这两个 \(1\) 前面至少有两个 \(1\),那么可以把前一个 \(1\) 删掉,再把后一个 \(1\) 提到刚好比前面最小的两个 \(1\) 大的位置,操作次数为 \(O(1.5\log k)\)

posted @ 2022-12-24 09:19  top_tree  阅读(55)  评论(0)    收藏  举报