codeforces #268 div2 D

对于这道题第一感觉是图论相关
然后我们先分析,假设a[i]在A集合需要的元素是a[x],在B集合是a[y]
那么假设a[i]在A集合,那必然a[x]也必须在A集合,由于a[y]如果在B集合就没有对应元素,则a[y]也一定在A集合
同理,当a[i]在B集合,a[x],a[y]一定也要在B集合
对此我们可以分析出,要想有解,那么a[i],a[x],a[y]必定在同一集合
这样我们可以构造出一堆堆团,每个团都只可能在唯一的集合
那这个团属于那个集合呢?假如这个团有一个元素a[j]它有一个不存在对应在A集合的元素,
那么这个团一定是在B集合的,否则反之;
这样我们也很容易想到什么时候无解,那一定是某个团中既存在一个元素不存在对应在A集合的元素,又存在一个元素不存在对应在B集合的元素
所以就很好解决了,我们用n+1,n+2分别表示不存在对应在A集合的元素,不存在对应在B集合的元素
不难想到用并查集维护团,然后搞定(其实不难,可惜现场nc没想出来)

 1 var ans,a,fa,c:array[0..100010] of longint;
 2     p,q,x,i,n:longint;
 3 
 4 procedure swap(var a,b:longint);
 5   var c:longint;
 6   begin
 7     c:=a;
 8     a:=b;
 9     b:=c;
10   end;
11 
12 function getf(x:longint):longint;
13   begin
14     if fa[x]<>x then fa[x]:=getf(fa[x]);
15     exit(fa[x]);
16   end;
17 
18 procedure sort(l,r: longint);
19   var i,j,x,y: longint;
20   begin
21     i:=l;
22     j:=r;
23     x:=a[(l+r) shr 1];
24     repeat
25       while a[i]<x do inc(i);
26       while x<a[j] do dec(j);
27       if not(i>j) then
28       begin
29         swap(a[i],a[j]);
30         swap(c[i],c[j]);
31         inc(i);
32         j:=j-1;
33       end;
34     until i>j;
35     if l<j then sort(l,j);
36     if i<r then sort(i,r);
37   end;
38 
39 function find(x:longint):longint;
40   var l,r,m:longint;
41   begin
42     l:=1;
43     r:=n;
44     while l<=r do
45     begin
46       m:=(l+r) shr 1;
47       if a[m]=x then exit(m);
48       if a[m]>x then r:=m-1
49       else l:=m+1;
50     end;
51     exit(-1);
52   end;
53 
54 procedure union(x,y:longint);
55   var k1,k2:longint;
56   begin
57     k1:=getf(x);
58     k2:=getf(y);
59     if k1<>k2 then fa[k2]:=k1;
60   end;
61 
62 begin
63   readln(n,p,q);
64   for i:=1 to n do
65   begin
66     read(a[i]);
67     c[i]:=i;
68     fa[i]:=i;
69   end;
70   fa[n+1]:=n+1;
71   fa[n+2]:=n+2;
72   sort(1,n);
73 
74   for i:=1 to n do
75   begin
76     x:=find(p-a[i]);
77     if x<>-1 then union(i,x)
78     else union(i,n+1);
79     x:=find(q-a[i]);
80     if x<>-1 then union(i,x)
81     else union(i,n+2);
82   end;
83   if getf(n+1)=getf(n+2) then
84   begin
85     writeln('NO');
86     halt;
87   end;
88   writeln('YES');
89   for i:=1 to n do
90     if getf(i)=getf(n+1) then ans[c[i]]:=1 else ans[c[i]]:=0;
91   for i:=1 to n do
92   begin
93     write(ans[i]);
94     if i<>n then write(' ');
95   end;
96   writeln;
97 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473136.html