Codeforces Round #268 (Div. 1) B. Two Sets

题目链接B. Two Sets

题意:把n个数分到A,B两个集合里面,如果x在A里面则a-x也在A里面,如果x在B里面则b-x也在B里面,

题解:用并查集维护,如果a-x存在并且b-x不存在,则把x和a-x放到A集合,如果b-x存在并且a-x不存在,则把x和b-x放到B集合,都不存在就输出no,
关键是都存在的情况,我们先把,x,a-x,b-x,归到同一个集合,然后再根据a-x,b-x,的情况去判放到那个集合,如果最后都没有判到到底归到那个集合的话,,就可以随便归到A,B,任意一个

#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define PI 3.14159265
using namespace std;
const int maxn=1e5+5;
int n,a,b;
map<int,int>mp;
int fa[maxn];
int num[maxn];
void init()
{
	for(int i=0;i<=n+1;i++)
	{
		fa[i]=i;
	}
}
int find(int x)
{
	if(x==fa[x])
	{
		return x;
	}
	else
	{
		return fa[x]=find(fa[x]);
	}
}
void unite(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x==y)return ;
	fa[x]=y; 
}
int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>a>>b;
	int tmp=0;
	for(int i=1;i<=n;i++)
	{
		cin>>num[i];
		mp[num[i]]=i;
		tmp=max(tmp,num[i]);
	}
	if(tmp>=max(a,b))
	{
		cout<<"NO\n";return 0;
	}
	init();
	for(int i=1;i<=n;i++)
	{
		if(mp[a-num[i]])
			unite(i,mp[a-num[i]]);	
		else
			unite(i,n+1);
		if(mp[b-num[i]])
			unite(mp[b-num[i]],i);
		else
			unite(i,0);
	}
	int A=find(0);
	int B=find(n+1);
//	cout<<A<<' '<<B<<'\n'; 
	if(A!=B)
	{
		cout<<"YES"<<'\n';
		for(int i=1;i<=n;i++)
		{
			if(find(mp[num[i]])==A)
			{
				cout<<0<<' ';
			}
			else
			{
				cout<<1<<' ';
			}
		}
	}
	else
	{
		cout<<"NO\n";return 0;
	}
	return 0;
 } 
posted @ 2017-10-21 14:08  lhclqslove  阅读(147)  评论(0编辑  收藏  举报