D. Two Sets

Two Sets
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Little X has n distinct integers: p1, p2, ..., pn. He wants to divide all of them into two sets A and B. The following two conditions must be satisfied:

  • If number x belongs to set A, then number a - x must also belong to set A.
  • If number x belongs to set B, then number b - x must also belong to set B.

Help Little X divide the numbers into two sets or determine that it's impossible.

Input

The first line contains three space-separated integers n, a, b (1 ≤ n ≤ 105; 1 ≤ a, b ≤ 109). The next line contains n space-separated distinct integers p1, p2, ..., pn (1 ≤ pi ≤ 109).

Output

If there is a way to divide the numbers into two sets, then print "YES" in the first line. Then print n integers: b1, b2, ..., bn (bi equals either 0, or 1), describing the division. If bi equals to 0, then pi belongs to set A, otherwise it belongs to set B.

If it's impossible, print "NO" (without the quotes).

Examples
input
Copy
4 5 9
2 3 4 5
output
YES
0 0 1 1
input
Copy
3 3 4
1 2 4
output
NO
Note

It's OK if all the numbers are in the same set, and the other one is empty.


解题思路:

首先我们先假设存在一种合理的方案,则有  对于任一个数x,肯定在a,b集合中的一个。同时如果方案合理,最后的结果a,b集合中的元素没有交集。

1.对于一个数x,如果a-x不存在,则x肯定在b分组中(假定分组成立),则把x和b分组并起来;如果同时b-x也不存在的话,则再把x和a分组并起来,此时a和b分组被并了起来,显然这种方案不合理。

2.对于一个数x,如果a-x存在,则把x和a-x对应的下标并起来,此时并不能说明x属于集合a,因为可能存在N=2,a=8,b=20,4,16,这样的数据,只有当b-x不存在时,才把x和a的下标并起来。

3,如果b-x也存在时,就把x和b-x也的下标也并起来,此时如果x!=a-x!=b-x时,说明a和b集合公用x,即这种方案a和b被并起来,这种方案也不合理。此时如果x==a-x!=b-x,显然应分组为b,当然特例就是a和b相等,此时任何分组都可以。


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include<iomanip>
using namespace std;
typedef long long ll;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define pi acos(-1)
#define N 100005

int f[N],num[N];
map <int ,int> mp;
int findd(int x)
{
	return x!=f[x]?f[x]=findd(f[x]):f[x];
}

void mergee(int x,int y)
{
	int fx=findd(x);
	int fy=findd(y);
	if(fx!=fy)
		f[fx]=fy;
	return ;
}

int main()
{
	int n,A,B;
	while(~scanf("%d%d%d",&n,&A,&B))
	{
		memset(f,0,sizeof(f));
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&num[i]);
			mp[num[i]]=i;
		}
		for(int i=1;i<=n+2;i++)
		   f[i]=i;
		for(int i=1;i<=n;i++)
		{
			if(mp[A-num[i]]) mergee(i,mp[A-num[i]]);
			else mergee(i,n+2);
			if(mp[B-num[i]]) mergee(i,mp[B-num[i]]);
			else mergee(i,n+1);
		}
		int x=findd(n+1);
		int y=findd(n+2);
		if(x==y) puts("NO");
		else
		{
			puts("YES");
			for(int i=1;i<=n;i++)
			{
				if(findd(i)==findd(n+1)) printf("0 ");
				else printf("1 ");
			}
			printf("\n");
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值