题意:
有n个编号分别为1~n的立方体以及两种操作,一种是move操作,一种是count操作。move操作就是让你把含x的一堆立方体移到含y的一堆立方体的上面,count操作就是让你求出编号为x的立方体底下有几个立方体。
解析:
一看到这道题,很容易就能想到用并查集来做,而这道题也的确是用并查集来做的O(∩_∩)O~
首先,我们先来考虑move操作。当你要把两堆立方体堆在一起时,可以把底下那堆的堆顶的father更新为上面那堆的堆顶,这应该是很容易想到的。
那么,应该如何求出编号为x的立方体底下的方块数呢?
我们可以用Under[x]来记录编号为x的立方体底下有多少个方块,这样,输出时只要输出Under[x]即可。
可是我们不可能持续更新Under[x],这样的复杂度太大了,因此,我们可以用一个Up[]数组来记录每个立方体到它所在的那堆立方体的堆顶的距离,这样只要持续更新每一堆的堆顶的Under[]值即可。
而这一步只需在合并时就能顺便完成了,几乎无需任何复杂度。
并且,Up[]数组的更新也是非常容易的,只需在并查集函数getfa()中加一句Up[x]+=Up[f[x]]即可。
这样一来,就可以发现Under[x]=Under[getfa(x)]-Up[x],因此输出时只要输出Under[getfa(x)]-Up[x]就可以了。
代码如下:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#define max(x,y