闲话
来点不同的大炮打蚊子的非 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$。否则直接合并。
代码和上面一样的。
完整代码
代码里前半段注释是本题正常的 STL 做法,感兴趣的也可以学习一下。