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 }