Give you a Set

Give you a Set

  • Description

    给你n个初始集合:{1}, {2}, {3}, …, {n}.,即每个集合中只有1个元素,第i(1<=i<=n)个集合中含有元素i。现在我们要对这n个集合做一些有趣的操作:
    操作1:1 p q
    解释: 合并 p 元素与q元素所在集合,如果p与q已经在一个相同的集合中了,忽略这个操作
    操作 2:2 p q
    解释 :把元素 p 移动到 元素 q 所在集合,如果p与q已经在一个相同的集合中了,忽略这个操作
    操作 3: 3 p
    解释 :返回包含元素p的集合的元素个数与该集合元素的总和

  • Input

    输入有许多测试用例,每个测试用例第一行为n与m( 1 <=n,m<=100000 ),分别代表初始集合的总数,与 操作总数。以下m行为m个操作,保证操作合法,即1<=p,q<=n。输入到文件尾。输入文件大小不超过 5 M。

  • Output

    对于每个操作3,输出两个整数:该集合元素的个数 与 集合中元素的总和。

  • Sample Input

5 7
1 1 2
2 3 4
1 3 5
3 4
2 4 1
3 4
3 3

  • Sample Output

3 12
3 7
2 8

  • Hint

    初始集合:{1}, {2}, {3}, {4}, {5}
    操作 1 1 2 后 :{1,2}, {3}, {4}, {5}
    操作 2 3 4 后 :{1,2}, {3,4}, {5}( 忽略空集合 )
    操作 1 3 5 后 :{1,2}, {3,4,5}
    操作 2 4 1 后 :{1,2,4}, {3,5}

 #include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

#define N 200010
int father[N],num[N];
int sum[N];
int n,m;

int find(int a)
{
    int r=a;
    while(father[r]!=r) r=father[r];
    for(int l=a,t;l!=r;l=t)
    {
        t=father[l];
        father[l]=r;
    }
    return r;
}

void merge(int a,int b)
{
    int aa=find(a),bb=find(b);
    if(aa==bb)  return ;
    int m=min(aa,bb);
    father[aa]=father[a]=m;father[bb]=father[b]=m;
    sum[aa]+=sum[bb];sum[bb]=sum[aa];
    num[aa]+=num[bb];num[bb]=num[aa];
}

void link(int a,int b)
{
    int aa=find(a),bb=find(b);
    if(aa==bb)  return ;
    father[a]=bb;
    num[aa]--,num[bb]++;
    sum[aa]-=a,sum[bb]+=a;
}

void query(int a)
{
    int aa=find(a);
    printf("%d %d\n",num[aa],sum[aa]);
}
void init()
{
    for(int i=1;i<=n;i++)
    {
        father[i]=n+i;
    }
    for(int i=n+1;i<=2*n;i++)
    {
        father[i]=i;
    }
    for(int i=n+1;i<=2*n;i++)
    {
        num[i]=1;
        sum[i]=i-n;
    }
}


int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        init();
        int c,a,b;
        while(m--)
        {
            scanf("%d",&c);
            switch(c)
            {
                case 1:scanf("%d %d",&a,&b);merge(a,b);break;
                case 2:scanf("%d %d",&a,&b);link(a,b);break;
                case 3:scanf("%d",&a);query(a);break;
                default:;
            }
        }
    }
    return 0;
}

你可能感兴趣的:(Give you a Set)