[HNOI2012]永无乡 (pb_ds/并查集)

看了友人的pb_ds介绍就写了这道题

友情链接:http://blog.csdn.net/mistilteinn/article/details/60325660

用并查集维护连通性,启发式合并时暴力插入即可,相当短,比用线段树还短

之所以要用这种鬼畜的写法而不用pair是因为null_type在老版本编译器中会CE,换成

tree,rb_tree_tag,tree_order_statistics_node_update>

就没问题了

代码:

#include
#include
#include
#include
#include
using namespace std;
using namespace __gnu_pbds;
inline int R()
{
	int r=0;char c=getchar();
	while(c<'0'||c>'9')c=getchar();
	while(c>='0'&&c<='9'){r=r*10+c-'0';c=getchar();}
	return r;
}
typedef tree,rb_tree_tag,tree_order_statistics_node_update> Tr;
const int M=100005;
Tr T[M];
Tr::point_iterator it;
int fa[M];
int get_fa(int o)
{
	if(fa[o]==o) return o;
	return fa[o]=get_fa(fa[o]);
}
inline void merge(int a,int b)
{
	a=get_fa(a);b=get_fa(b);
	if(a==b) return;
	if(T[a].size()>T[b].size()) swap(a,b); 
	for(it=T[a].begin();it!=T[a].end();it++) T[b].insert(*it);
	fa[a]=b;
}
int main()
{
	int n,m,a,b;
	char c;
	n=R();m=R();
	for(int i=1;i<=n;i++) T[i].insert(make_pair(R(),i)),fa[i]=i;
	while(m--) merge(R(),R());
	m=R();
	while(m--)
	{
		scanf(" %c",&c);a=R();b=R();
		if(c=='B') merge(a,b);
		else
		{
			a=get_fa(a);
			if(b>T[a].size()) puts("-1");
			else printf("%d\n",T[a].find_by_order(b-1)->second);
		}
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/ulita/p/6568298.html

你可能感兴趣的:([HNOI2012]永无乡 (pb_ds/并查集))