HDU 2818 Building Block【并查集+根节点偏移量】
大意:有30000个木块一次在一条线上排开 现在有两种操作 一种是把a木块所在的木块堆全部放到b木块堆的上面
一种是 查询a木块底下有多少块
分析:并查集 偏移量代表相对于根节点的偏移量
一下为根方便建立 然后对于一个下根 用一个数组表示其最顶端的是什么
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 30005; 7 8 int fa[maxn]; 9 int num[maxn]; 10 int di[maxn]; 11 12 void init(int n) { 13 for(int i = 0; i <= n; i++) { 14 fa[i] = i; 15 num[i] = 0; 16 di[i] = i; 17 } 18 } 19 20 int Find(int x) { 21 if(x == fa[x]) return fa[x]; 22 int fax = fa[x]; 23 fa[x] = Find(fa[x]); 24 num[x] = num[x] + num[fax]; 25 return fa[x]; 26 } 27 28 int main() { 29 int n; 30 char a; int x, y; 31 while(EOF != scanf("%d",&n) ) { 32 init(30000); 33 while(n--) { 34 scanf("\n%c",&a); 35 if(a == 'M') { 36 scanf("%d %d",&x, &y); 37 int xx = Find(x); int yy = Find(y); 38 Find(di[xx]); Find(di[yy]); 39 // printf("%d %d %d %d id = %d %d\n", x, y, xx, yy, di[xx], di[yy]); 40 if(xx != yy) { 41 fa[xx] = yy; 42 num[xx] = num[di[yy]] + 1; 43 di[yy] = di[xx]; 44 } 45 } else { 46 scanf("%d",&x); 47 int z = Find(x); 48 printf("%d\n", num[x]); 49 } 50 } 51 } 52 return 0; 53 }
有一点需要注意的是 每次更新完都要进行更新 要不可能会出现这次更新的不会对上次产生影响 也就是第38行