238.银河英雄传说
思路
本质上是一个带深度和集合大小的带权并查集问题
本题中深度表示相隔的战舰数量,集合大小表示所在列中有多少战舰
当执行 M 指令时,第 j 号战舰所在列要接上战舰 i 所在的列,即 p[find(i)] = find(j); d[find(j)]的深度就要加上战舰 i 所在列的大小,即 d[find(j)] += s[find(i)]; 接上之后,战舰j所在列集合大小要变,s[find(j)] += s[find(i)];
当执行 C 指令时,通过find找到 i 和 j 是否在同一个集合,间隔战舰数量就是通过 d 计算,abs(d[i]-d[j]-1)就是距离
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3e4 + 10;
int t;
int p[N], d[N], s[N];
int find(int x) {
    if (p[x] != x) {
        int t = find(p[x]);
        d[x] += d[p[x]];
        p[x] = t;
    }
    return p[x];
}
int main() {
    cin >> t;
    for (int i = 1; i <= N; i++) {
        p[i] = i;
        s[i] = 1;
        d[i] = 0;
    }
    while (t --) {
        char ops;
        cin >> ops;
        int a, b;
        cin >> a >> b;
        int pa = find(a), pb = find(b);
        if (ops == 'M') {
            p[pa] = pb;
            d[pa] += s[pb];
            s[pb] += s[pa];
        } else {
            if (pa == pb) {
               cout << max(abs(d[b] - d[a]) - 1, 0) << endl;
            } else {
                cout << -1 << endl;
            }
        }
    }
    return 0;
}