[US Open 2004][luogu2342] 叠积木 [带权并查集]

题面

洛谷传送门

思路

学了4年多OI,第一次知道还有带权并查集这个东西

wtcl

这个玩意儿的原理和详细实现,可以参考这个博客:带权并查集传送门

这道题,就是在带权并查集的基础上,加个维护每个集合的大小。

并查集往每堆积木的底部那个上面合并(也就是根是最底下的积木),合并的时候把儿子的value设定成父亲的size即可

Code

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cassert>
#define ll long long
using namespace std;
inline int read(){
	int re=0,flag=1;char ch=getchar();
	while(ch>'9'||ch<'0'){
		if(ch=='-') flag=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
	return re*flag;
}
int n=30000,m,f[100010],siz[100010],val[100010];
inline int find(int x){//带权并查集的路径压缩+权值维护
	if(x==f[x]) return x;
	int tmp=f[x];
	f[x]=find(f[x]);
	val[x]+=val[tmp];
	return f[x];
}
int main(){
	m=read();int i;
	char s[10];int t1,t2,x,y;
	for(i=1;i<=n;i++) f[i]=i,siz[i]=1,val[i]=0;
	while(m--){
		scanf("%s",s);
		if(s[0]=='M'){
			t1=read();t2=read();
			x=find(t1);
			y=find(t2);
			f[x]=y;//合并到底部
			val[x]=siz[y];//权值和集合大小的关系
			siz[y]+=siz[x];
		}
		else{
			t1=read();
			x=find(t1);
			printf("%d\n",val[t1]);
		}
	}
}
			
posted @ 2019-11-02 16:30  dedicatus545  阅读(222)  评论(0编辑  收藏  举报