acwing 238. 银河英雄传说 并查集

Posted itdef

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了acwing 238. 银河英雄传说 并查集相关的知识,希望对你有一定的参考价值。

地址 https://www.acwing.com/problem/content/240/

有一个划分为N列的星际战场,各列依次编号为1,2,…,N。

有N艘战舰,也依次编号为1,2,…,N,其中第i号战舰处于第i列。

有T条指令,每条指令格式为以下两种之一:

1、M i j,表示让第i号战舰所在列的全部战舰保持原有顺序,接在第j号战舰所在列的尾部。

2、C i j,表示询问第i号战舰与第j号战舰当前是否处于同一列中,如果在同一列中,它们之间间隔了多少艘战舰。

现在需要你编写一个程序,处理一系列的指令。

输入格式

第一行包含整数T,表示共有T条指令。

接下来T行,每行一个指令,指令有两种形式:M i j或C i j。

其中M和C为大写字母表示指令类型,i和j为整数,表示指令涉及的战舰编号。

输出格式

你的程序应当依次对输入的每一条指令进行分析和处理:

如果是M i j形式,则表示舰队排列发生了变化,你的程序要注意到这一点,但是不要输出任何信息;

如果是C i j形式,你的程序要输出一行,仅包含一个整数,表示在同一列上,第i号战舰与第j号战舰之间布置的战舰数目,如果第i号战舰与第j号战舰当前不在同一列上,则输出-1。

数据范围

N30000,T500000

输入样例:
4
M 2 3
C 1 2
M 2 4
C 4 2
输出样例:
-1
1

当一个队列转移到另一个队列下面的时候 就合并了

可以考虑使用并查集

1  5  8  9   --->  1  8   9

2  6                   2

3  7                   3

4                       4

                         5

                         6

                         7

但是距离就不好统计了

我们可以再开 一个数组记录每个元素到队列的距离 合并的时候也只需要更新队列首部的距离和该队列元素数 其他元素的距离可以留到find函数递归的时候再行更新

有点类似线段树的lazy操作

比如图1中 元素4 距离队列头部1 距离为3  

队列头部1距离为0  队列元素为4

元素7 距离队列5 距离为2 

队列头部元素5 记录该队列size为3

合并后

更新队列元素1 size为7 

更新元素5距离队列头部距离为4(也就是之前队列头部元素1记录的size)

元素 6 7 的实际距离可以在并查集find函数调用时候再计算 也就是  元素6距离队列首部距离= 元素5距离队列首部距离4+ 元素6距离原来的队首元素5的距离1

代码如下

#include <iostream>



using namespace std;
const int N = 31000 + 10;
int fa[N], n, t, i, j, d[N], size_[N];//size就是记录个数
int get(int x)
{
    if (x == fa[x])
        return x;
    int root = get(fa[x]);
    d[x] += d[fa[x]];//往下推进
    return fa[x] = root;
}
void merge(int x, int y)
{
    x = get(x), y = get(y);
    fa[x] = y, d[x] = size_[y];
    size_[y] += size_[x];//顺带记录
}
int main()
{
    scanf("%d
", &t);
    for (i = 1; i <= 30000; i++)
        fa[i] = i, size_[i] = 1;
    while (t--)
    {
        char ch = getchar();
        scanf("%d %d
", &i, &j);
        if (ch == M)
            merge(i, j);
        else
        {
            if (get(i) == get(j))
                cout << abs(d[i] - d[j]) - 1;
            else
                cout << "-1";
            cout << endl;
        }
    }
    return 0;
}

 

以上是关于acwing 238. 银河英雄传说 并查集的主要内容,如果未能解决你的问题,请参考以下文章

238. 银河英雄传说边带权的并查集

ACWing 238 银河英雄传说

P1196 [NOI2002] 银河英雄传说(并查集)

银河英雄传说 - 带权并查集

银河英雄传说(带权并查集)

并查集银河英雄传说