Building Block
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4430 Accepted Submission(s): 1373
M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command.
C X : Count the number of blocks under block X
You are request to find out the output for each C operation.
6 M 1 6 C 1 M 2 4 M 2 6 C 3 C 4
1 02
题意+思路参考别人:进行m次操作,M x y 将包含x的集合移动到y上面,C x, 计算x下面有几个元素。用p[x]表示x的根结点,
cnt[x]表示x所在集合的元素个数,top[x]表示x上面有几个元素。每次进行路径压缩时,top[x]都要加上
top[p[x]],cnt和p的操作就是并查集的基本操作。最后计算结果是用x所在集合元素的个数 - 在它之上
的个数 - 它本身。
代码:#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 30010 int pre[N]; int s[N]; int top[N]; int finds(int x) { int t; if(x!=pre[x]) { t=pre[x]; pre[x]=finds(pre[x]); top[x]+=top[t]; } return pre[x]; } void mix(int a,int b) { int x=finds(a),y=finds(b); if(x!=y) { pre[y]=x; top[y]=s[x]; s[x]+=s[y]; } } int main() { int T; scanf("%d",&T); char op[2]; int x,y; for(int i=1;i<=N;i++) { pre[i]=i; top[i]=0; s[i]=1; } while(T--) { scanf("%s",op); if(op[0]=='M') { scanf("%d %d",&x,&y); mix(x,y); } else { scanf("%d",&x); int nx=finds(x); printf("%d\n",s[nx]-top[x]-1); } } return 0; }