【解题报告】 [NOI2002]银河英雄传说

【解题报告】[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

posted @ 2019-08-04 23:21  wweiyi  阅读(165)  评论(0编辑  收藏  举报
js脚本