I hope you know the beautiful Union-Find structure. In this problem, you’re to implement something similar, but not identical. The data structure you need to write is also a collection of disjoint sets, supporting 3 operations:
Initially, the collection contains n sets: {1}, {2}, {3}, . . . , {n}.
题意:
涉及到并查集的删除操作
1 合并这两个集合
2 将p移到q集合中去
3 统计元素个数和全部元素的和 相当于询问输出结果
5 7 ->5个集合,7种操作
1 1 2
2 3 4
1 3 5
3 4 ->3 12
2 4 1
3 4 ->3 7
3 3 ->2 8
#include<iostream> #include<stdio.h> using namespace std; typedef long long ll; const int N=1e5+10; int f[N*2],ii[N*2],num[N*2]; ll sum[N*2]; int n,m,cnt; void init() { for(int i=1;i<=n;i++) { f[i]=i; ii[i]=i; sum[i]=i; num[i]=1; } cnt=n; } int getf(int x) { if(f[x]==x) return x; return f[x]=getf(f[x]); } void merge(int x,int y) { int t1=getf(ii[x]); int t2=getf(ii[y]); if(t1!=t2) f[t2]=t1; num[t1]+=num[t2]; sum[t1]+=sum[t2]; } void deletee(int x) { int p=ii[x]; sum[getf(p)]-=x; num[getf(p)]--; ii[x]=++cnt; sum[ii[x]]=x; num[ii[x]]=1; f[ii[x]]=ii[x]; } int main() { int op,p,q; while(~scanf("%d %d",&n,&m)) { init(); for(int i=1;i<=m;i++) { scanf("%d",&op); if(op==1)//合并这两个集合 { scanf("%d %d",&p,&q); if(getf(ii[p])==getf(ii[q])) continue; else merge(p,q); } else if(op==2)//将p移到q集合中去 { scanf("%d %d",&p,&q); if(getf(ii[p])!=getf(ii[q]))//如果不在同一个集合中 { deletee(p); merge(p,q); } } else if(op==3)//统计元素个数和全部元素的和 相当于询问输出结果 { scanf("%d",&p); int k=getf(ii[p]); printf("%d %lld\n",num[k],sum[k]); } } } return 0; }