zoukankan      html  css  js  c++  java
  • 计蒜客练习题:接龙(带权并查集)

    蒜头君在玩一种接龙的游戏,蒜头君有 30000张卡片分别放在 30000列,每列依次编号为 1,2,...,30000。 同时,蒜头君也把每张卡片依次编号1,2,...,30000。

    游戏开始,蒜头君让让第i张卡片处于第i(i=1,2,...,30000)列。

    然后蒜头君会发出多次指令,每次调动指令M i j会将第i张卡片所在的队列的所有卡片, 作为一个整体(头在前尾在后)接至第j张卡片所在的队列的尾部。

    蒜头君还会查看当前的情况,发出C i j的指令,即询问电脑,第i张卡片与第 j张卡片当前是否在同一个队列中, 如果在同一列中,那么它们之间一共有多少张卡片。

    聪明的你能不能编写程序处理蒜头君的指令,以及回答蒜头君的询问呢? 输入格式 第一行有一个整数T(1≤T≤500000),表示总共有T条指令。以下有T行,每行有一条指令。

    指令有两种格式: M i j: i和j是两个整数(1≤i,j≤30000),表示指令涉及的卡片编号。

    你需要让第i张卡片所在的队列的所有卡片,作为一个整体(头在前尾在后)接至第j 张卡片所在的队列的尾部, 输入保证第i号卡片与第 j 号卡片不在同一列。

    C i j:i和j是两个整数(1≤i,j≤30000),表示指令涉及的卡片编号。该指令是蒜头君的询问指令。

    输出格式:如果是蒜头君调动指令,则表示卡片排列发生了变化,你的程序要注意到这一点,但是不要输出任何信息;

    如果是蒜头君的询问指令,你的程序要输出一行,仅包含一个整数,表示在同一列上, 第i号卡片与第j号卡片之间的卡片数目(不包括第i张卡片和第j 张卡片)。

    如果第i号卡片与第j号卡片当前不在同一个队列种中,则输出−1。

    样例输入:

    4
    M 2 3
    C 1 2
    M 2 4
    C 4 2

    样例输出:

    -1
    1


    AC代码(参考网上):
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    const int MAXN = 30000 + 5;
    
    int father[MAXN], dis[MAXN], Size[MAXN];
    int n, k, ans;
    
    int Find(int x)
    {
        if (x == father[x]) return x;
        int temp = father[x];
        father[x] = Find(father[x]);
        dis[x] = (dis[x] + dis[temp]);
        return father[x];
    }
    
    void Union(int x, int y)
    {
        int fx = Find(x), fy = Find(y);
        if (fx != fy)
        {
            father[fx] = fy;
            dis[fx] = Size[fy];
            Size[fy] += Size[fx];
        }
    }
    
    int check(int x, int y)
    {
        int ans = -1;
        if (Find(x) == Find(y))
            ans = abs(dis[x] - dis[y]) - 1;
        return ans;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n;
        for(int i = 1; i <= n; i++)
            father[i] = i, dis[i] = 0, Size[i] = 1;
        ans = 0;
        while (n--)
        {
            string a; 
            int b, c;
            cin >> a >> b >> c;
            if (a == "C") cout << check(b, c) << endl;
            else Union(b, c);
        }
        return 0;
    }
    View Code
    感觉看看代码也是懂为什么这样写的,但是当自己写的时候还是要参考网上的题解。(这可能是因为我太菜了吧
    网上的人都说这是一道带权并查集的模板题,很easy(然而菜鸡并不这么想
    仔细想想主要是dis的合并那一块写不出来,之后没想到要开一个size数组来记录整个集合的元素(天真的我只想开一个dis完事儿
    唉,还是在明天再写写看看是不是真的懂了吧。


  • 相关阅读:
    如果男人是计算机,女人是软件(在开发过程中的偶然随想)
    C/C++ 可变参数函数的原理和应用
    Python学习记录Hello Word
    Unity 把数字,英文图片变成字体
    unity+Android+PC加载本地图片
    Python学习记录安装
    Android学习 问题与答案
    Android 第三方 APK 包的静默安装
    Android学习 问题与答案 (2)
    JNI 之 HelloWorld
  • 原文地址:https://www.cnblogs.com/Vikyanite/p/11832420.html
Copyright © 2011-2022 走看看