小X有n个互不相同的整数: p1,p2,...,pn 。他想把这些整数分到两个集合A和B里边。但是要符合下面两个条件。
· 如果x属于A,那么a-x也肯定属于A。
· 如果x属于B,那么b-x也肯定属于B。
判断一下是否存在一种方案来分配这些数字到集合A,B中。
注意:如果一个集合为空也是可以的。
Input
单组测试数据。 第一行有三个整数n,a,b (1≤n≤10^5; 1≤a,b≤10^9)。 第二行有n个不一样的整数 p1,p2,...,pn (1≤pi≤10^9).
Output
如果可行,那么输出YES,否则输出NO。
Input示例
样例输入1 4 5 9 2 3 4 5
Output示例
样例输出1 YES
此题的思路与 hiho一下 第一百三十四周 #1468 : 2-SAT·hihoCoder新春晚会 【2-SAT 之 枚举--搜索】 类似
都是从头开始枚举这个点的两个情况---然后收到这个枚举影响的点加入队列继续枚举----看情况是否成立。
可以先预处理出来每个数的A连点和B连点。
当考虑 i 为A时 ,判断 i 和 i的A连点是否可以为A --可以的话将 i和i的A连点 放入队列并标记---
当从队列中取时 , 判断 i 是否有 B连点, 当有B连点j的话,因为 i 已进入A ,那么 j 就不能进入B --- 即只能进入A -------- (如果有矛盾的情况,则枚举失败,所有此次枚举标记的点恢复未标记状态。)
考虑 i 为 B 的方法与上面一致-.- ------------- 飘过-.-
代码:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[100100],b[100100][2],ans[100100];
queue<int > qa;
stack<int > sa;
void my_clear()
{
while (!qa.empty())
qa.pop();
}
void myjinA(int x)
{
qa.push(x);
sa.push(x);
}
int main()
{
int t,A,B,k,x,y;
cin>>n>>A>>B;
for (int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
memset(b,-1,sizeof(b));
memset(ans,-1,sizeof(ans));
bool fafe=true;
for (int i=0;i<n;i++)
{
k=lower_bound(a,a+n,A-a[i])-a;
if (k>=0&&k<n&&a[k]==A-a[i])
b[i][0]=k;
k=lower_bound(a,a+n,B-a[i])-a;
if (k>=0&&k<n&&a[k]==B-a[i])
b[i][1]=k;
if (b[i][0]==b[i][1]&&b[i][0]==-1)
fafe=false;
}
if (!fafe)
{
printf("NO\n");
return 0;
}
for (int i=0;i<n;i++)
{
if (ans[i]==-1)
{
//---------入A
if (b[i][0]!=-1&&ans[i]==-1&&ans[b[i][0]]==-1)
{
my_clear();
x=i;y=b[x][0];
myjinA(x);
myjinA(y);
ans[x]=0;
ans[y]=0;
while (!qa.empty())
{
x=qa.front();
qa.pop();
if (b[x][1]!=-1&&ans[b[x][1]]==-1)
{
x=b[x][1];
if (b[x][0]!=-1&&ans[b[x][0]]==-1)
{
y=b[x][0];
myjinA(x);
myjinA(y);
ans[x]=0;
ans[y]=0;
}
else
{
fafe=false;
}
}
if (!fafe) break;
}
if (!fafe)
{
while (!sa.empty())
{
x=sa.top();
sa.pop();
ans[x]=-1;
}
}
}
//入B
if (b[i][1]!=-1&&ans[i]==-1&&ans[b[i][1]]==-1)
{
fafe=true;
my_clear();
x=i;y=b[x][1];
myjinA(x);
myjinA(y);
ans[x]=1;
ans[y]=1;
while (!qa.empty())
{
x=qa.front();
qa.pop();
if (b[x][0]!=-1&&ans[b[x][0]]==-1)
{
x=b[x][0];
if (b[x][1]!=-1&&ans[b[x][1]]==-1)
{
y=b[x][1];
myjinA(x);
myjinA(y);
ans[x]=1;
ans[y]=1;
}
else
{
fafe=false;
}
}
if (!fafe) break;
}
if (!fafe)
{
while (!sa.empty())
{
x=sa.top();
sa.pop();
ans[x]=-1;
}
}
}
if (!fafe) break;
}
if (ans[i]==-1)
{
fafe=false;break;
}
}
if (fafe)
printf("YES\n");
else
printf("NO\n");
return 0;
}
/*
3 11 12
4 7 8
3 5 6
2 3 4
*/