题目:
小X有n个互不相同的整数: p1,p2,…,pn 。他想把这些整数分到两个集合A和B里边。但是要符合下面两个条件。
· 如果x属于A,那么a-x也肯定属于A。
· 如果x属于B,那么b-x也肯定属于B。
判断一下是否存在一种方案来分配这些数字到集合A,B中。
注意:如果一个集合为空也是可以的。(数据结构,Hash,并查集,CodeForces)
其实不是很懂这个题跟并查集的联系,看到有这个标签分类,就边查资料边做了一下。
只要判断(a-x)或者(b-x)在集合中,如果两个都在的话,就进一步判断(a-(b-x))或者(b-(a-x))是否在集合中即可。
解决代码:
#include <iostream>
#include <algorithm>
#define maxl 10000000
using namespace std;
int n,a,b;
int ns[maxl]={0};
bool sear(int number)
//用二分法进行查找
{
int l = 0,r = n-1,mid;
while(l <= r)
{
mid = (r+l)/2;
if(ns[mid] > number)
r = mid-1;
else if(ns[mid] < number)
l = mid+1;
else
return true;
}
return false;
}
int main()
{
while(~scanf("%d%d%d",&n,&a,&b))
{
for(int i = 0;i < n;i++)
{
scanf("%d",&ns[i]);
}
sort(ns,ns+n);//sort函数对数组进行升序排列,方便二分法查找
for(int i = 0;i <= n;i++)
{
bool n1 = sear(a-ns[i]);
bool n2 = sear(b-ns[i]);
if(!n1 && !n2)//在两个集合中的任何一个都可以
{
printf("NO!\n");
return 0;
}
if(n1 && n2)//两个集合都满足,则进行深层考虑
{
bool n3 = sear(b-(a-ns[i]));
bool n4 = sear(a-(b-ns[i]));
if(!n3 && !n4)
{
printf("NO!\n");
return 0;
}
}
}
printf("YES!\n");
return 0;
}
}
补充一个用到的知识点:
sort函数:包含于头文件中,这个函数可以传两个参数或三个参数。第一个参数是要排序的区间首地址,第二个参数是区间尾地址的下一地址。也就是说,排序的区间是 [a,b) 。简单来说,有一个数组 int a[100] ,要对从 a[0] 到 a[99] 的元素进行排序,只要写 sort(a,a+100) 就行了,默认的排序方式是升序。