POJ1988 Cube stacking(非递归)

n有N(N<=30,000)堆方块,开始每堆都是一个方块。方块编号1 – N. 有两种操作:
nM x y : 表示把方块x所在的堆,拿起来叠放到y所在的堆上。
nC x : 问方块x下面有多少个方块。
n操作最多有 P (P<=100,000)次。对每次C操作,输出结果。
 
 
这题挺厉害的,真的不容易想 

 

 

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<string>
 5 #include<algorithm>
 6 using namespace std;
 7 #define MAX 30007
 8 int bc[MAX],under[MAX],sum[MAX];
 9 void Init()
10 {
11     for(int i=0;i<MAX;i++) {
12         bc[i] = i;
13         sum[i] = 1;
14         under[i] = 0;
15     }
16 }
17 
18 int find(int son)
19 {
20     int fa = son,ans = 0;
21 
22     while(bc[fa]!=fa)
23     {
24         ans += under[fa];
25         fa = bc[fa];
26     }
27     //return fa;
28     //Path Compression
29     int temp = son,k,k1;
30     while(bc[temp]!=fa)
31     {
32         k = bc[temp];
33         bc[temp] = fa;
34         k1 = under[temp];
35         under[temp] = ans;
36         ans -= k1;
37         temp = k;
38     }
39     return fa;
40 }
41 
42 void merge(int a,int b)
43 {
44     if(a == b) return ;
45     a = find(a);
46     b = find(b);
47     if(a != b){
48         bc[a] = b;
49     }
50     under[a] = sum[b];
51     sum[b] += sum[a];
52 }
53 
54 int main(int argc, char const *argv[]) {
55     int p;
56     while(scanf("%d",&p)!=EOF)
57     {
58         Init();
59         char s[2];
60         int x,y,c;
61         while(p--)
62         {
63             scanf("%s",s);
64             if(s[0] == 'M'){
65                 scanf("%d%d",&x,&y);
66                 merge(x,y);
67             }
68             else{
69                 scanf("%d",&c);
70                 find(c);
71                 printf("%d\n",under[c]);
72             }
73         }
74     }
75     return 0;
76 }

 

posted @ 2017-07-30 15:23  swallowblank  阅读(244)  评论(0编辑  收藏  举报