蒜头君在玩一种接龙的游戏,蒜头君有 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
#include<iostream>
#define FATHER_SIZE 30000
using namespace std;
int father[FATHER_SIZE];
int dis[FATHER_SIZE];
int sizes[FATHER_SIZE];
int intial()
{
int i;
for(i=0;i<FATHER_SIZE;++i)
{
father[i]= i;
sizes[i]=1;
}
}
int find_father(int x)
{
if(father[x]==x)
{
return x;
}
else
{
int y = father[x];
father[x]=find_father(y);
dis[x]+= dis[y];
return father[x];
}
}
void merge(int a,int b)
{
int x,y;
x= find_father(a);
y= find_father(b);
if(x != y)
{
father[x]= y;
dis[x] = sizes[y];//接在最后面
sizes[y]+= sizes[x];
}
// cout<<x<<" 的大哥是 "<<y<<endl;
// cout<<x<<" 的小弟有 "<<sizes[x]<<" 个 "<<endl;
// cout<<x<<" 到大哥之间的小弟有 "<<dis[x]<<" 个 "<<endl;
}
int search(int x,int y)
{
if(find_father(x)== find_father(y))
{
// cout<<x<<" 到大哥之间的小弟有 "<<dis[x]<<endl;
// cout<<y<<" 到大哥之间的小弟有 "<<dis[y]<<endl;
if(dis[x]>dis[y])
{
return dis[x]-dis[y]-1;
}
else
{
return dis[y]-dis[x]-1;
}
}
else
{
return -1;
}
}
int main()
{
char a;
int b,c;
int i,n,k;
cin>>n;
intial();
//初始化
for(i=0;i<n;++i)
{
cin>>a>>b>>c;
if(a=='M')
{
merge(b,c);
}
if(a=='C')
{
cout<<search(b,c)<<endl;
}
}
return 0;
}