総乗客ニンニク演習:ソリティア(加重互いに素セット)

蒜头君在玩一种接龙的游戏,蒜头君有 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>
 使用して 名前空間をSTD。

CONST  INT MAXN = 30000 + 5 

int型の父[MAXN]、DIS [MAXN]、サイズ[MAXN]。
整数N、K、ANS。

int型の検索(int型x)は、
{
    もし(x ==父[X])戻りX。
    int型温度= 父[X];
    父[X] = 検索(父[X]);
    DIS [X] =(DIS [X] + DIS [TEMP])。
    戻り父[X];
}

無効連合(int型のx、int型のy)
{
    INT FX =(X)を検索FY = (y)を探します。
    もし(FX!= 年度)
    {
        父[FX] = FY;
        DIS [FX] = サイズ[FY]。
        サイズ[FY] + = サイズ[FX]。
    }
}

INTチェック(int型のx、int型Y)
{
    int型 ANS = - 1 ;
    もし(検索(x)は== 検索(Y))
        年間 = ABS(例えば[X] -たとえば[Y]) - 1 リターン歳;
}

int型のmain()
{
    イオス:: sync_with_stdio();
    cinを >> N;
    以下のためにINT iが= 1 ; I <= N; I ++ 
        父[I] = I、DIS [I] = 0、サイズ[I] = 1 
    ANS = 0 ;
    しばらく(N-- 
    {
        文字列A; 
        int型B、C;
        CIN >> B >> C。
        もし(== " C ")COUT <<検査(B、C)<< ENDL。
        連合(B、C);
    }
    リターン 0 ;
}
コードの表示
感觉看看代码也是懂为什么这样写的,但是当自己写的时候还是要参考网上的题解。(这可能是因为我太菜了吧
网上的人都说这是一道带权并查集的模板题,很easy(然而菜鸡并不这么想
仔细想想主要是dis的合并那一块写不出来,之后没想到要开一个size数组来记录整个集合的元素(天真的我只想开一个dis完事儿
唉,还是在明天再写写看看是不是真的懂了吧。


おすすめ

転載: www.cnblogs.com/Vikyanite/p/11832420.html