题意:
给你n个数,让你把它们分为两个集合(集合可以为空)。
要求,如果过把 x 放到A集合中,a - x必须也在A集合中;同理,把 x 放到B集合中,b-x也要在B集合中。
如果可以满足要求输出YES,并输出分配情况;否则输出NO。
思路:
*我开始还以为n为奇数时一定是NO,像6 - 3 = 3这种情况要注意一下。
x1—(a)—x2—(b)—x3—(a)—x4—(b)—x5…… (表示x1+x2 = a,x2+x3 = b,x3+x4 = a……)
给我一个x,我就会按上面的链进行dfs。
记相加为a的个数为cota,相加为b的个数为cotb。
如果cota == cotb,说明无论怎么分都会有冲突。
否则择其大者而放之,即如果cota > cotb,把这次dfs所遇到的点,全部放入A组中。否则,全部放入B组。
AC代码:(代码写得比较麻烦)
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL;
const int MAXN = 1e5+5;
int ycsm[MAXN];
struct em
{
int v, s, index;
}d[MAXN];
bool cmp(em t, em c)
{
return t.v < c.v;
}
bool cmp2(em a, em b)
{
return a.index < b.index;
}
int cota, cotb, cot;
int n, a, b;
int bs(int tmp) //get the tmp's index;
{
int l = 0, r = n-1;
while(l <= r)
{
int mid = (l+r)/2;
if(d[mid].v == tmp) return mid;
if(d[mid].v < tmp) l = mid+1;
else r = mid-1;
}
return -1;
}
void dfs(int val, int ab)
{
int tmp, next;
if(ab == 0)
{
tmp = a-val, next = bs(tmp); //next is index;
if(next == -1) return;
ycsm[cot++] = next;
cota++;
dfs(tmp, 1);
}
else if(ab == 1)
{
tmp = b-val;
next = bs(tmp);
if(next == -1) return;
ycsm[cot++] = next;
cotb++;
dfs(tmp, 0);
}
else
{
next = bs(a-val);
if(next != -1)
{
cota++;
ycsm[cot++] = next;
dfs(a-val, 1);
}
//
next = bs(b-val);
if(next != -1)
{
cotb++;
ycsm[cot++] = next;
dfs(b-val, 0);
}
}
}
int main()
{
//input
cin>>n>>a>>b;
for(int i = 0;i < n; i++)
{
cin>>d[i].v;
d[i].s = -1;
d[i].index = i;
}
//
sort(d, d+n, cmp);
//a == b
if(a == b)<span style="white-space:pre"> </span>//特判了一下a等于b的情况,不知道有没有。。。
{
for(int i = 0;i < n; i++)
{
int tmp = a - d[i].v;
int next = bs(tmp);
if(next == -1) return puts("NO"), 0;
}
puts("YES");
for(int i = 0;i < n; i++)
printf("0%c",i == n-1?'\n':' ');
return 0;
}
//a != b
int i, tmp;
for(i = 0;i < n; i++)
{
if(d[i].s != -1) continue;
cota = cotb = cot = 0;
ycsm[cot++] = i;<span style="white-space:pre"> </span>//把当前这个点的下标放入待分配数组。
dfs(d[i].v, 2);
if(cota == cotb) break;<span style="white-space:pre"> </span>//无论怎么放都会有冲突,break
if(cota > cotb) tmp = 0;<span style="white-space:pre"> </span>
else tmp = 1;
for(int j = 0;j < cot; j++)<span style="white-space:pre"> </span>//更新每个值所对应的组别。
d[ycsm[j]].s = tmp;
}
if(i != n)
puts("NO");
else
{
puts("YES");
sort(d, d+n, cmp2);
for(int i = 0;i < n; i++)
printf("%d%c",d[i].s,i == n-1?'\n':' ');
}
return 0;
}