并查集——集合问题
题目描述
给你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
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=1e5+50;
int n,a,b,vis[maxn],f[maxn];
map<int,int> flag;
int find(int x)
{
if(vis[x]==x){
return x;
}
else{
vis[x]=find(vis[x]);
return vis[x];
}
}
void merge(int a,int b)
{
int p=find(a);
int q=find(b);
if(p==q){
return ;
}
else{
vis[q]=p;
return ;
}
}
int main()
{
cin>>n>>a>>b;
int mx=0;
for(int i=1;i<=n;i++){
cin>>f[i];
flag[f[i]]=i;
mx=max(mx,f[i]);
}
if(mx>=max(a,b)){
cout<<"NO"<<endl;
}
else{
for(int i=0;i<=n+1;i++){
vis[i]=i;
}
for(int i=1;i<=n;i++){
if(flag[a-f[i]]){
merge(i,flag[a-f[i]]);
}
else{
merge(n+1,i);
}
if(flag[b-f[i]]){
merge(i,flag[b-f[i]]);
}
else{
merge(0,i);
}
}
int A=find(0);
int B=find(n+1);
if(A!=B){
cout<<"YES"<<endl;
for(int i=1;i<=n;i++){
if(i!=1){
cout<<" ";
}
if(find(i)==A){
cout<<"0";
}
else{
cout<<"1";
}
}
cout<<endl;
}
else{
cout<<"NO"<<endl;
}
}
return 0;
}