H

//带删除操作的并查集
//题意:给你一个1~n的集合,有三种操作
// 1: 把p和q所在的集合合并
//2:把p移到q所在的集合中
//3:返回p所在集合中的元素个数和元素的和

//第二种操作不能直接把p的father改成q的father,因为这样p的子树也都换了爸爸
//对于每个元素,我们可以记录它所在的位置pos,合并的时候新申请一个pos,然后让这个元素的位置指向pos,再把pos和q合并 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

const int N=2e5+5;

int n,m;
int opt,p,q;
struct Node
{
    Node *fa,*pos;
    int key;
    int cnt,sum;
}node[N];

typedef Node* Tree;
Tree now_node;

int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        return num*10+c-'0';
    return num;
}

void init()
{
    now_node=node;
    for(int i=0;i<=n;++i,++now_node)
    {
        now_node->key=i;
        now_node->cnt=1;
        now_node->sum=i;
        now_node->fa=now_node;
        now_node->pos=now_node;
//        (node+i)->cnt=(node+i)->sum=0;
//        (node+i)->fa=(node+i);
//        (node+i)->pos=(node+i);
    }
    //now_node=(node+n);
}

Tree find(Tree x)
{
    return x->fa==x?x:x->fa=find(x->fa);
}

void unionn(Tree a,Tree b)
{
    Tree fa=find(a),fb=find(b);
    if(fa==fb)
        return;
    fa->fa=fb;
    fb->cnt+=fa->cnt;
    fb->sum+=fa->sum;
}

void move(Tree a)
{
    Tree fa=find(a->pos);
    --fa->cnt;
    fa->sum-=a->key;
    ++now_node;
    now_node->key=a->key;
    now_node->cnt=1;
    now_node->sum=a->key;
    now_node->fa=now_node;
    a->pos=now_node;
}

int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        init();
        while(--m)
        {
            opt=read();
            if(opt==1)
            {
                p=read(),q=read();
                unionn((node+p)->pos,(node+q)->pos);
            }
            else if(opt==2)
            {
                p=read(),q=read();
                Tree fa=find((node+p)->pos);
                Tree fb=find((node+q)->pos);
                if(fa!=fb)
                {
                    move(node+p);
                    unionn((node+p)->pos,(node+1)->pos);
                }
            }
            else
            {
                p=read();
                Tree fa=find((node+p)->pos);
                printf("%d %d
",fa->cnt,fa->sum);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lovewhy/p/8463623.html