题解:P15352 [COCI 2025/2026 4] 魔术 Magija
P15352 [COCI 2025/2026 #4] 魔术 / Magija
思路
倍增并查集,以下描述忽略反阿克曼函数 $\alpha(n)$。
首先考虑直接 $O(nq)$ 的维护,显然简单,用并查集维护哪些点可以相互到达,合并时压缩路径并统计答案,数据比较水所以甚至有 $73$ 分。
[73 pts Code]
1 |
|
然后这个东西的时间复杂度瓶颈显然在修改操作,我们发现有些点会被重复合并,但是由于合并方式比较奇怪,我们不能很容易地记录那些点可以跳过不合并。
这时我们考虑一个很妙的数据结构:倍增并查集。
众所周知,倍增的时间复杂度是 $O(\log n)$,并查集的时间复杂度是 $O(n)$,那么将这两者结合的这个数据结构就是 $O(n\log n)$。
咋做呢?我们考虑在并查集根节点数组中添加一维 $k$ 代表合并的深度,即区间长度为 $2^k$。
- 改写
find操作:find找本层的根节点值。 - 改写
join操作:join只合并本层的值。
但是这样显然不对,我们需要增加一些操作:
merge:拆分每一个操作区间,也就是倍增部分;update:维护答案,本题是单点查询所以只记录最低层(主要是出题人给了一个极小的空间限制)。
这两个操作怎么写呢?
首先讲解 merge:
我们每次将整个区间拆解成两个大小相等的子区间,分治地操作,层数减一,若不在最底层,则合并,若在最底层,则用 update 修改答案。
同时若要合并的两个值已经合并过了,则它们的子区间也一定合并过了,这也是本算法的优化之处。
再讲解 update:
首先默认是最底层,然后与 join 类似,只是多了一步答案更新。
对于每次 $l,r,len$ 的修改,我们倍增地 merge 操作,对应地更新 $l,r$ 端点即可。
代码
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 House_of_Fan!