中文题:
链接:https://ac.nowcoder.com/acm/problem/15167
来源:牛客网
题目描述
给你a,b和n个数p[i],问你如何分配这n个数给A,B集合,并且满足:
若x在集合A中,则a-x必须也在集合A中。
若x在集合B中,则b-x必须也在集合B中。
这题我想的很简单。。没去搞并查集。。虽然我是在练习并查集。。。。
如果暴力想法就是一个一个遍历下去,但是既然能遍历那么就能二分
所以我们二分找到距离 a- arr[i] 或 b-arr[i] 最近的值,再判断能不能把它也加入集合,如果所有都抛一遍后还有没被分配的肯定这个数组无法被分两组,不然就输出标记就是了。
以下 是 AC 代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int arr[maxn];
int vis[maxn];
int main()
{
int n,a,b;
scanf("%d%d%d",&n,&a,&b);
for(int i=0;i<n;i++)
scanf("%d",&arr[i]);
sort(arr,arr+n);
memset(vis,0,sizeof vis);
bool flag = 0;
for(int i=0;i<n;i++)
{
if(!vis[i])
{
int a0 = lower_bound(arr,arr+n,a-arr[i]) - arr;
int b0 = lower_bound(arr,arr+n,b-arr[i]) - arr;
if(!vis[b0] && arr[b0] + arr[i] == b)
{
vis[b0] = vis[i] = 1;
}
else if(!vis[a0] && arr[a0] + arr[i] == a)
{
vis[a0] = vis[i] = 2;
}
}
}
for(int i=0;i<n;i++)
{
if(vis[i] == 0)
{
flag = 1;
break;
}
}
if(flag) puts("NO");
else
{
puts("YES");
for(int i=0;i<n;i++)
{
printf("%d%c",vis[i]%2,i==n-1?'\n':' ');
}
}
return 0;
}