zoukankan      html  css  js  c++  java
  • 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;
    }
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    React元素渲染
    初识JSX
    微信小程序复制文本到剪切板
    微信小程序报错request:fail url not in domain list
    小程序,通过自定义编译条件,模拟推荐人功能
    积分抵扣逻辑
    微信小程序 switch 样式
    tomcat 配置开启 APR 模式
    tomcat8 传输json 报错 Invalid character found in the request target. The valid characters are defined in RFC 3986
    c++数组初始化误区
  • 原文地址:https://www.cnblogs.com/itdef/p/12109611.html
Copyright © 2011-2022 走看看