------------只要够努力,人生最坏的结局不过是大器晚成!!!

链接:https://www.nowcoder.com/acm/contest/77/D
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

给你a,b和n个数p[i],问你如何分配这n个数给A,B集合,并且满足:

若x在集合A中,则a-x必须也在集合A中。

若x在集合B中,则b-x必须也在集合B中。

输入描述:

第一行 三个数 n a b  1<=n<=1e5  1<=a,b<=1e9
第二行 n个数 p1 p2 p3...pn 1<=pi<=1e9

输出描述:

如果可以恰好分开就输出第一行 YES
然后第二行输出 n个数 分别代表pi 是哪个集合的 0 代表是A集合 1代表是B 集合
不行就输出NO
放在哪个集合都可以的时候优先放B
示例1

输入

4 5 9
2 3 4 5

输出

YES
0 0 1 1
示例2

输入

3 3 4
1 2 4

输出

NO

题意:

给你a,b和n个数p[i],问你如何分配这n个数给A,B集合,并且满足:

若x在集合A中,则a-x必须也在集合A中。

若x在集合B中,则b-x必须也在集合B中。

思路:

对于一个x来说,能分成以下4种情况(这里a!=b):

1.a-x不存在,b-x不存在。这种情况直接输出NO。

2.a-x存在,b-x不存在。这种情况把x和a-x放在集合A中。

3.a-x不存在,b-x存在。这种情况把x和b-x放在集合B中。

4.a-x存在,b-x存在。这种情况比较我们就不能直接确定要放A还是要放B了。

那么我们接下还需要判断是否存在y有a-y=b-x或者b-y=a-x其中之一存在。为什么是其中之一呢?

假设有a-y=b-x和b-y=a-x同时存在,那么将两式子相减有x-y=y-x -> x*2=y*2 -> x=y成立,则有a-y=a-x=b-x -> a=b矛盾。所以上面两种情况只可能存在一种或都不存在。如果存在a-y=b-x,那么就把x和a-x和y和a-y(b-x)都放到集合A中。同理b-y=a-x存在的情况。

如果都不存在,那么我们就无法决则把x和a-x和b-x放到集合A中还是集合B中,因为放到那一边都会剩下另一个无法去放,所以就输出NO。这里用并查集来维护即可。


#include <bits/stdc++.h>
using namespace std;
const int Max = 1e5 + 5;
map <int, int> mp;
int fa[Max], f[Max], n, a, b;

void init(){
	for(int i = 0; i <= n + 1; i++){  //注意初始化的范围0~n+1 
		fa[i] = i;
	}
}
/*
int find(int x){    
	int i = x;
	while(i != fa[i]){
		i = fa[i];
	}
	int j = x;
	while(fa[j] != i){     //数据压缩 
		int k = fa[j];
		fa[j] = i;
		j = k;
	}
	return i;
}
*/
int find(int x){  
	if(fa[x] == x)
		return x;
	else 
		return fa[x] = find(fa[x]);   //也压缩了,更简洁 
} 

void Union(int x, int y){
	int i = find(x);
	int j = find(y);
	if(i != j){
		fa[i] = j;
	}
}

int main(){
	cin >> n >> a >>b;
	int mymax = -1;
	for(int i = 1; i <= n; i++){
		cin >> f[i];
		mp[f[i]] = i;
		mymax = max(mymax, f[i]);
	}
	if(mymax > max(a, b)){
		cout << "NO" << endl;
	}
	else{
		init();
		for(int i = 1; i <= n; i++){
			if(mp[b - f[i]])			 //如果b-f[i]存在	
				Union(i, mp[b - f[i]]);  //b-f[i]存在就i和b-f[i]的映射放在一个集合里面 
			else						
				Union(i, 0);			 //不存在是就只能讲i放入到0集合即(a集合)
			if(mp[a - f[i]])
				Union(i, mp[a - f[i]]);
			else
				Union(i, n + 1); 
		}
		int f1 = find(0);
		int f2 = find(n + 1);
		if(f1 == f2){			//一个数两个集合里都必须有,产生矛盾
			cout << "NO" << endl;
		}
		else{
			cout << "YES" << endl;
			for(int i = 1; i <= n; i++){
				if(i != 1)
					cout << " ";
				if(find(i) == f1){    //f[i]的映射和0在同一个集合,这输出0,表示在A集合 
					cout << 0;
				}
				else
					cout << 1;
			}
			cout << endl;
		}
	}
	return 0;
} 
/*
可以手动走一遍: 
6 5 9
2 3 4 5 1 8
*/ 

  

 
posted on 2018-03-04 11:19  ystraw  阅读(301)  评论(0)    收藏  举报

不经一番切孤寒,怎得梅花扑鼻香