标签:
题意:有n个方块栈,一开始每个栈里只有一个方块,方块编号为栈编号,两种操作,一种是把方块a所在的栈全放在方块b所在的栈上面,另一种要求输出方块a的下面有多少个方块。
解法:并查集。用数组size[i]维护以i为根的集合大小,数组ans[i]维护方块i下面有多少方块,那么当两个栈合并时,栈a的底的ans即为栈b的size,而两个栈合并后根还是栈b的栈底,所以栈b的size+=栈a的size;当查询一个方块a下面有多少方块时,ans[a]+=ans[father[a]]。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #include<iomanip> #define LL long long #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 using namespace std; int size[30005], ans[30005], father[30005]; int Find(int a) { if(father[a] != a) { int fa = father[a]; father[a] = Find(father[a]); ans[a] += ans[fa]; } return father[a]; } void Union(int a, int b) { int fa = Find(a), fb = Find(b); ans[fa] = size[fb]; size[fb] += size[fa]; father[fa] = fb; } int main() { int q; scanf("%d", &q); for(int i = 0; i <= 30000; i++) size[i] = 1; for(int i = 0; i <= 30000; i++) father[i] = i; memset(ans, 0, sizeof ans); while(q--) { char op[2]; int a, b; scanf("%s%d", op, &a); if(op[0] == ‘M‘) { scanf("%d", &b); Union(a, b); } else { Find(a); printf("%d\n", ans[a]); } } return 0; }
标签:
原文地址:http://www.cnblogs.com/Apro/p/4954183.html