题解:
用两个变量来维护:
1.sz[i]维护第i列元素的个数
2.pre[x]维护第x元素到当前队首的距离。
在并查集是不断维护这两个值。
至于如何维护看下图和文字解释
当然,这样维护还是不够的,对于pre数组我么会发现:
对于任意一个飞船,我们都知道它的祖先(不一定是队头,但一定间接或直接指向队头),还知道距离它祖先的距离。对于每一个飞船,它到队头的距离,就等于它到它祖先的距离加上它祖先到队头的距离 pre[x]+=pre[f[x]];(在并查集过程中不断维护即可)
/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
//#define int long long
#define endl '\n'
using namespace std;
const int maxn=5e5+10;
const int mod=1e9+7;
int f[maxn],pre[maxn],sz[maxn];
int ifind(int x){
if(x==f[x]) return x;
int fn=ifind(f[x]);
pre[x]+=pre[f[x]];
return f[x]=fn;
}
void init(){
for(int i=0;i<maxn;i++){
sz[i]=1;
f[i]=i;
}
}
signed main(){
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
init();
int n;
cin>>n;
for(int i=0;i<n;i++){
char c;
int x,y;
cin>>c;
cin>>x>>y;
int dx=ifind(x);
int dy=ifind(y);
if(c=='M'){
pre[dx]+=sz[dy];
sz[dy]+=sz[dx];
f[dx]=dy;
sz[dx]=0;
}
else{
if(dx!=dy) cout<<-1<<endl;
else cout<<abs(pre[x]-pre[y])-1<<endl;
}
}
}