题目思路
这题卡了好久 看了题解才知道咋做
用带权并查集维护某一块下面的块的数量sum和这个连通块里面的块数up
用up数组更新根节点的sum值 再在压缩路径的时候对路径上的块更新sum
ac代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e6+5;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1000000007;
//998244353
int f[maxn],sum[maxn],up[maxn];
int findx(int x)
{
if(x!=f[x])
{
int t=f[x];//保存父亲节点的值
f[x]=findx(f[x]);//压缩路径至根节点
sum[x]+=sum[t];//从根结点向上跟新
}
return f[x];
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<=n;i++)
{
f[i]=i,sum[i]=0,up[i]=1;
}
for(int i=1;i<=n;i++)
{
char a[4];
int x,y;
scanf("%s",a);
if(a[0]=='M')
{
scanf("%d%d",&x,&y);
int r1=findx(x);
int r2=findx(y);
if(r1==r2)continue;
f[r1]=r2;//因为我们要从下往上跟新 所以让在下面的做根结点
sum[r1]+=up[r2];//跟新旧根节点的值
up[r2]+=up[r1];//跟新整个连通块里面的块数量
}
if(a[0]=='C')
{
scanf("%d",&x);
findx(x);//跟新当前块下面的块的数量
printf("%d\n",sum[x]);
}
}
}