闲话

来点不同的大炮打蚊子的非 STL 的做法。

题目翻译

你有 $n$ 个盒子,每个盒子一开始装了一个颜色为 $c_i$ 的球。

有 $q$ 次询问(操作),每次询问给出一对 $(a,b)$,要把盒子 $a$ 的所有球转到盒子 $b$ 里,问此时 $b$ 里有多少颜色不同的球。

$1\leq n,q\leq 2\times 10^5,1\leq a,b,c_i\leq n$。

题目思路

考虑使用根号分治。

显然的阈值为 $B=\sqrt n\approx 450$。

对于目前球个数 $\geq B$ 的盒子,我们记录一个桶 $bkt_{i,j}$ 表示序号(不是编号)为 $i$ 的盒子是否装了 $j$。

因为这样的盒子数只有 $\leq B$ 个,所以我们需要记录一个序号,设编号为 $i$ 的盒子的序号为 $id_i$。

然后对于装球个数 $\lt B$ 的盒子,我们记录 $arr_{i,j}$ 表示编号为 $i$ 的盒子的第 $j$ 个装的是什么。

大和大在一起,我们可以直接 $O(n)$ 转移。可以证明这样子转移的次数不会超过 $B$ 次。

小并到大的,直接扫一遍小的往大的里塞。

大并到小的,和上面同理。但我们无需新开一个 $id$,直接 $id_b\gets id_a$ 继承一下就可以。

小的和小的在一起,我们需要讨论一下。如果新出来的集合大小是 $\geq B$ 的,我们需要新开一个 $id$。否则直接合并。

代码和上面一样的。

完整代码

AT submission 47747560

代码里前半段注释是本题正常的 STL 做法,感兴趣的也可以学习一下。

最后修改:2023 年 11 月 19 日
v我50吃疯狂星期四