传送门:51nod 1557
题目大意:
题目意思有点绕,大家好好理解一下,我就不再复述了。只需要注意是互不相同的整数。
思路:
很容易知道,数字应该是成对出现的,即若两个数满足 x、a-x 的关系则都在集合 A,若两个数满足 x、b-x 的关系则都在集合 B。
我们只考虑不符合条件的情况,由于数互不相同,对于某个数 x ,如果既不存在 a-x 属于集合 A,又不存在 b-x 属于集合 B,则为 NO。
对于某个数 x,如果既存在 a-x 又存在 b-x,就一定不行吗? 不是的,也有可能存在一个数字 d 使得 x 和 a-x 是一对,d 和 b-x是一对,或者, x 和 b-x 是一对,d 和 a-x 是一对。是一对的意思就是它们属于同一个集合。
换种适合编程的描述就是:对于数x ,若 a-x 和 b-x 都存在。如果 x 属于集合 A,则 b-x 一定不属于集合 B,否则 x 就会冲突。所以 b-x 一定属于集合 A,则必存在 a-(b-x) 属于集合 A。反之,如果 x 属于集合 B,则 a-x 一定不属于集合 A,否则 x 就会冲突。所以 a-x 一定属于集合 B,则必存在 b-(a-x) 属于集合 B。
除了以上的三种情况,剩下的都是合法的了,输出 YES。
说的自己都晕了……慢慢理解吧……
具体实现:
由于数据范围为 10^5,所以应该采用低于 O(n^2) 的算法,这里用的是二分。先排序,后用 lower_bound 函数对每个 x 判断是否存在 a-x 和 b-x 以及 a-(b-x) 和 b-(a-x)。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int i,n,a,b,f,pa,pb,pc,pd,p[100010];
scanf("%d%d%d",&n,&a,&b);
for(i=0;i<n;i++) scanf("%d",&p[i]);
sort(p,p+n);
f=1;
for(i=0;i<n;i++)
{
pa=lower_bound(p,p+n,a-p[i])-p; //a-x 的位置
pb=lower_bound(p,p+n,b-p[i])-p; //b-x 的位置
pc=lower_bound(p,p+n,a-(b-p[i]))-p; //a-(b-x) 的位置
pd=lower_bound(p,p+n,b-(a-p[i]))-p; //b-(a-x) 的位置
if((p[pa]!=a-p[i]&&p[pb]!=b-p[i]))
{ //如果 a-x 和 b-x 都不存在
f=0;
break;
}
if((p[pa]==a-p[i]&&p[pc]!=a-(b-p[i]))&&(p[pb]==b-p[i]&&p[pd]!=b-(a-p[i])))
{ //在 a-x和 b-x都存在的情况下,如果 a-(b-x)和 b-(a-x)都不存在
f=0;
break;
}
}
if(f) printf("YES\n");
else printf("NO\n");
return 0;
}