【解题报告】[NOI2002]银河英雄传说
题目:luogu P1196
题意简述
处理M个指令,都为两种如下形式的指令之一
1.M i j 表示让第i好战舰所在列的全部战舰保持原有顺序,接在第j好战舰所在列的尾部。
2.C i j,表示询问第i号战舰与第j号战舰当前是否处于同一列中,如果在同一列中,它们之间间隔了多少艘战舰。如果不在同一列中,输出-1;
解题思路
并查集
第二个指令我们要知道i,j两号战舰差多少,维护一个数列d即可,d[x]代表x前面的战舰数量,要查询的时候,我们只要知道i,j两号前面各有多少战舰,然后i前面的减去j前面的绝对值减一就可以了。
而第一个指令就是简单地处理一下size,记录集合大小,也很简单
AC代码
#include <iostream>
#include <cstdio>
using namespace std;
int f[30005];
int d[30005];
int size[30005];
int t;
int jdz(int x)
{
return x>0? x:(-x);
}
void init()
{
for(int i=1;i<=30000;i++)
{
f[i]=i;
size[i]=1;
}
}
int get(int x)
{
if(x==f[x])
return x;
int root=get(f[x]);
d[x]+=d[f[x]];
return f[x]=root;
}
void merge(int x,int y)
{
x=get(x),y=get(y);
f[x]=y;d[x]=size[y];
size[y]+=size[x];
}
int main()
{
cin>>t;
init();
for(int i=1;i<=t;i++)
{
char s[2];
int x,y;
scanf("%s",s);
cin>>x>>y;
if(s[0]=='M')
merge(x,y);
if(s[0]=='C')
{
if(get(x)==get(y))
cout<<jdz(d[x]-d[y])-1<<endl;
else
cout<<"-1"<<endl;
}
}
return 0;
}
数据情况https://www.luogu.org/record/22153408