1. 程式人生 > >(並查集狀態壓縮)CodeForces - 469D Two Sets

(並查集狀態壓縮)CodeForces - 469D Two Sets

queue == 劃分 查詢 sample 在那 des elong equal

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).

Example

Input
4 5 9
2 3 4 5
Output
YES
0 0 1 1
Input
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果a-x、b-x(如果存在)也必須存在在A,如果a-(b-x) 、b-(a-x)存在也必須在A……即所有數可以劃分為若幹個集合,每個集合中的元素必須同時屬於A或B。這可以通過並查集維護。如果某數x,a-x,b-x都不存在那麽這個數無法放到A、B任何一個,直接輸出NO即可。

接下來維護並查集的狀態,采用狀態壓縮,用兩位2進制數表示可否放到A、B集合中。對於每個數x,如果a-x存在則其可以放在集合A,如果b-x存在則其可以放在集合B。對每個並查集取其集合內所有可行狀態的交集。顯然並查集之間是不再存在互相影響的。如果每個並查集可行狀態非0就表明一定存在符合題意的分配方式,任取每個集合的任意可行分配即可。

  1 #include <iostream>
  2 #include <string>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <queue>
  8 #include <set>
  9 #include <map>
 10 #include <list>
 11 #include <vector>
 12 #include <stack>
 13 #define mp make_pair
 14 //#define P make_pair
 15 #define MIN(a,b) (a>b?b:a)
 16 //#define MAX(a,b) (a>b?a:b)
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 const int MAX=1e5+5;
 20 const int MAX_V=25;
 21 const int INF=2e9+5;
 22 const double M=4e18;
 23 using namespace std;
 24 const int MOD=1e9+7;
 25 typedef pair<ll,int> pii;
 26 const double eps=0.000000001;
 27 #define rank rankk
 28 map<int,int> par;//父親
 29 map<int,int> rank;//樹的高度
 30 //初始化n個元素
 31 map<int,bool> chu;
 32 map<int,int> st;
 33 int an[MAX];
 34 void init(int n)
 35 {
 36     for(int i=1;i<n;i++)
 37     {
 38         par[i]=i;
 39         rank[i]=0;
 40     }
 41 }
 42 //查詢樹的根,期間加入了路徑壓縮
 43 int find(int x)
 44 {
 45     if(!par[x])
 46     {
 47         rank[x]=0;
 48         return par[x]=x;
 49     }
 50     if(par[x]==x)
 51         return x;
 52     else
 53         return par[x]=find(par[x]);
 54 }
 55 //合並x和y所屬的集合
 56 void unite(int x,int y)
 57 {
 58     x=find(x);
 59     y=find(y);
 60     if(x==y)
 61         return ;
 62     if(rank[x]<rank[y])
 63         par[x]=y;
 64     else
 65     {
 66         par[y]=x;
 67         if(rank[x]==rank[y])
 68             rank[x]++;
 69     }
 70 }
 71 //判斷x和y是否屬於同一個集合
 72 bool same(int x,int y)
 73 {
 74     return find(x)==find(y);
 75 }
 76 int n,a,b;
 77 int x[MAX];
 78 int main()
 79 {
 80     scanf("%d%d%d",&n,&a,&b);
 81     for(int i=1;i<=n;i++)
 82     {
 83         scanf("%d",&x[i]);
 84         chu[x[i]]=true;
 85     }
 86     for(int i=1;i<=n;i++)
 87         st[x[i]]=0;
 88     for(int i=1;i<=n;i++)
 89     {
 90         bool sta=false;
 91         if(chu[a-x[i]])
 92         {
 93             sta=true;
 94             unite(x[i],a-x[i]);
 95             st[x[i]]|=1;
 96         }
 97         if(chu[b-x[i]])
 98         {
 99             sta=true;
100             unite(x[i],b-x[i]);
101             st[x[i]]|=2;
102         }
103         if(!sta)
104             return 0*printf("NO\n");
105     }
106     for(int i=1;i<=n;i++)
107     {
108         st[find(x[i])]&=st[x[i]];
109     }
110     for(int i=1;i<=n;i++)
111         if(!st[x[i]])
112             return 0*printf("NO\n");
113     printf("YES\n");
114     for(int i=1;i<=n;i++)
115     {
116         if(st[find(x[i])]&1)
117             printf("0 ");
118         else
119             printf("1 ");
120     }
121     printf("\n");
122     return 0;
123 }

(並查集\狀態壓縮)CodeForces - 469D Two Sets