题意:
给定 n 个 方块, 然后有 p 个操作
操作M (a , b) , 就是将a方块所在的那一堆方块放到 b 上面。
操作C (x) , 就是询问x方块下面有多少方块
分析:
记录方块到父亲的距离dis, 还有最底的方块的cnt。
两个方块合并时,合并方块堆的父亲dis += 最底方块堆的cnt ,最底的方块堆的cnt 加上合并方块堆的 cnt
那么对于每个询问, 只要做一次路径压缩, 从根节点一直更新到询问点, 那么就能更新出询问点的长度
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int Maxn = 10 ; 4 int P; 5 int F[Maxn], cnt[Maxn], dis[Maxn]; 6 void init(){ 7 for(int i = 0; i < Maxn; i++) 8 F[i] = i, cnt[i] = 1, dis[i] = 0; 9 } 10 11 12 int Find (int x){ 13 if (F[x] != x){ 14 int temp = F[x]; //设置延时,最后从父节点回溯的时候再更新,注意与下面的对比 15 F[x] = Find(F[x]); 16 dis[x] += dis[temp]; 17 return F[x]; 18 } 19 return x; 20 } 21 22 /* 不能写成以下的形式, 因为这样会先更新了自己, 然后再更新父节点 23 int Find (int x){ 24 if (F[x] != x){ 25 dis[x] += dis[F[x]]; 26 F[x] = Find(F[x]); 27 return F[x]; 28 } 29 return x; 30 } 31 */ 32 33 34 int Merge(int a, int b){ 35 int t1 = Find(a), t2 = Find(b); 36 if(t1 != t2){ 37 F[t1] = t2; //将t1的根改为t2 38 dis[t1] = cnt[t2]; //那么t1到根的距离就是cnt[t2] 39 cnt[t2] += cnt[t1]; //然后cnt[t2]这一堆就要加上cnt[t1] 40 } 41 } 42 int main(){ 43 freopen("debug.txt","r", stdin); 44 init(); 45 scanf("%d", &P); 46 while(P--) 47 { 48 49 char ch[9]; 50 scanf("%s", ch); 51 if(ch[0] == 'M'){ 52 int a, b; 53 scanf("%d %d", &a, &b); 54 Merge(a,b); 55 } 56 else{ 57 int x; 58 scanf("%d", &x); 59 Find(x); 60 printf("%d ", dis[x]); 61 } 62 } 63 return 0; 64 }