HDU 2818 Building Block

題目:Building Block

鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2818

題意:

  有 n 個元素,初始分成 n 堆(每堆一個),接下來有 p 個操作:

  1. M x y  :將 下標爲x 的元素所在的堆 放在 y元素所在堆的上面

  2. C x     :問 下標爲x 的元素下方有多少元素。

思路:

  並查集的好題!!!

  普通並查集一般是問集合內的元素個數,這題問的是集合內指定元素下方的元素個數。

  這裏,我用了三個數組,fa[],son[],unum[],fa[x]表示x上方的元素,son[x]表示x下方的元素,unum[x]表示x下面的元素個數(包括x元素不包括son[x]下方的元素)。

  

  假設我現在要將L堆放在R堆上面,那麼son[C]就變成了D了,也就是L堆的最底層孩子的son值改爲R堆祖先下標。這裏的改變沒必要更改各元素的unum屬性,而在查詢下方元素個數時,遞歸的同時要主意路徑壓縮。

AC代碼:

 

 1 #include<stdio.h>
 2 #include<queue>
 3 using namespace std;
 4 #define N 30005
 5 
 6 int fa[N], son[N], unum[N];
 7 
 8 int find(int x)
 9 {
10   return fa[x]= fa[x]==x ? x : find(fa[x]);
11 }
12 
13 pair<int, int> findSon(int x)
14 {
15   if(son[x]==x) return make_pair(x, unum[x]);
16 
17   pair<int, int> ret = findSon(son[x]);
18   int child = ret.first;
19   int num = ret.second;
20 
21   unum[x] = unum[x] + num - unum[child];
22   son[x] = child;
23 
24   return make_pair(child, unum[x] + unum[child]);
25 }
26 
27 void mov(int x, int y)
28 {
29   int fx = find(x);
30   int fy = find(y);
31   if(fx==fy) return ;
32   else fa[fy]=fx;
33 
34   int sx = findSon(x).first;
35   son[sx] = fy;
36 }
37 
38 int main()
39 {
40   int m, x, y;
41   while(scanf("%d", &m)!=EOF)
42   {
43     for(int i=0; i<N; i++) fa[i]=i, son[i]=i, unum[i]=1;
44     while(m--)
45     {
46       char s[2];
47       scanf("%s", s);
48       if(s[0]=='M')
49       {
50         scanf("%d%d", &x, &y);
51         mov(x, y);
52       }
53       else
54       {
55         scanf("%d", &x);
56         printf("%d\n", findSon(x).second-1);
57       }
58     }
59   }
60   return 0;
61 }

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章