链接:https://www.nowcoder.com/acm/contest/77/D
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制: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
*/ 
 
                    
                
                
            
        
浙公网安备 33010602011771号