并查集之集合问题

在这里插入图片描述
首先知道p[i]≥1,所以不存在p[i]大于等于max(a,b)
用map<ll,ll>mp记录下每个p[i]出现的下标,每次找到b-p[i]或a-p[i]都进行一次连接

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int par[maxn];
int a[maxn];
int n;
map<int,int> mp;
void init(){
    
    
    for (int i=0;i<=n+1;i++){
    
    
        par[i]=i;//并查集初始化
    }
}
int find(int x){
    
    
    while(x!=par[x]){
    
    
        x=par[x];
    }
    return x;
}//查集
void unite(int x,int y){
    
    
    x=find(x);
    y=find(y);
    if(x!=y) par[x]=y;
}//并集
int main(){
    
    
    int A,B;
    cin>>n>>A>>B;
    int max1=0;
    for(int i=1;i<=n;i++){
    
    
        cin>>a[i];
        max1=max(max1,a[i]);
        mp[a[i]]=i;//标记
    }
    if(max1>max(A,B)){
    
    
        cout<<"NO"<<endl;
        return 0;//这种情况不可能
    }
    init();
    for(int i=1;i<=n;i++){
    
    
        if(mp[B-a[i]])
            unite(i,mp[B-a[i]]);
        else unite(i,0);//如果不可能,放进特殊集合
        if(mp[A-a[i]])
            unite(i,mp[A-a[i]]);
        else unite(i,n+1);
    }
    int af=find(0);
    int bf=find(n+1);
    if(af==bf){
    
     //a,b集合都不可能
        cout<<"NO"<<endl;
    }else{
    
    
        cout<<"YES"<<endl;
        for(int i=1;i<=n;i++){
    
    
            if(i!=1)cout<<' ';
            if(af==find(i))cout<<0;
            else cout<<1;
        }
        cout<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wuyvle/article/details/114380303