传送门:https://www.luogu.org/problemnew/show/P1196#sub
大家都说并查集按秩合并并没有用,所以我以后大概也不会写按秩合并了。
而且带权并查集,不能写按秩合并好像!
普通的并查集只能维护在不在同一个集合,合并到同一个集合,但是带权并查集就可以维护很多很多东西啦。
比如这个题目,我们就用带权并查集维护队伍的长度。还要维护前缀和。
注意:带权并查集的find函数不能随便写,因为每一次find都会压缩路径然后搞乱掉权值。
所以在需要的时候尽可能少的写find,这就是我的理解吧。如果有不会的请指出来哈
下面上代码,我们维护前缀和就完事了。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+7;
int p[maxn],s[maxn];
int sum[maxn];
void init()
{
for(int i=0;i<maxn;i++)
{
p[i] = i;
s[i] = 1;
}
}
int find(int x)
{
if(p[x]==x) return x;
int f = find(p[x]);
sum[x] += sum[p[x]];
return p[x] = f;
}
void unite(int x,int y)
{
x = find(x);
y = find(y);
if(x==y) return;
p[x] = y;
s[y] += s[x];
s[x] = 0;
}
bool same(int x,int y)
{
return find(x)==find(y);
}
int main()
{
int T;
cin>>T;
init();
while(T--)
{
char op;
int x,y;
cin>>op>>x>>y;
int fx = find(x);
int fy = find(y);
if(op=='M')
{
sum[fx] += s[fy];
p[fx] = fy;
s[fy] += s[fx];
s[fx] = 0;
}
else
{
if(fx!=fy)
{
cout<<-1<<endl;
}
else
{
cout<<abs(sum[x]-sum[y])-1<<endl;
}
}
}
return 0;
}