链接:
https://www.nowcoder.com/acm/contest/77/D
来源:牛客网
来源:牛客网
题目描述
给你a,b和n个数p[i],问你如何分配这n个数给A,B集合,并且满足:
若x在集合A中,则a-x必须也在集合A中。
若x在集合B中,则b-x必须也在集合B中。
输入描述:
第一行 三个数 n a b 1<=n<=1e5 1<=a,b<=1e9 第二行 n个数 p1 p2 p3...pn 1<=pi<=1e9
输出描述:
如果可以恰好分开就输出第一行 YES 然后第二行输出 n个数 分别代表pi 是哪个集合的 0 代表是A集合 1代表是B 集合 不行就输出NO
放在哪个集合都可以的时候优先放B
题解:
若有a-x2=x1,b-x3=x1;则x1可以与x2放到a中,
也可与x3放到b中,但是无论怎么放最后x1,x2,x3一定在同一集合中。
证明:一定不存在另一个数可以使a-x2=x0(x1与x2在a中的匹配是唯一的)。
同理x1与x3在b中的匹配也是唯一的。但是可能存在一个数使得
b-x2=x0,即x2与x0在b中匹配,那么此时x2与x0在b中(假设仅存在这四个数),
那么剩下的x1,x3也只能在b中匹配。
若存在一个数使a-x3=x0,则这四个数存在于a中。
若即有a-x3=x0,又有b-x2=x0,则这四个数可都在a或b中,据题意,b优先,
所以都在b中。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
int par[maxn],t[maxn];
map<int,int>mp;
void init()
{
for(int i=0;i<maxn;i++)
par[i]=i;
}
int find(int x)
{
if(par[x]==x)return x;
return par[x]=find(par[x]);
}
void unite(int x,int y)
{
x=find(x);y=find(y);
if(x!=y)
par[x]=y;
}
int main()
{
init();
int n,a,b;scanf("%d%d%d",&n,&a,&b);
int ma=0;
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&t[i]);
ma=max(ma,t[i]);
mp[t[i]]=i;
}
if(ma>=max(a,b))
{
printf("NO\n");
return 0;
}
for(int i=1;i<=n;i++)
{
if(mp[a-t[i]])unite(i,mp[a-t[i]]);
else unite(i,n+1);
if(mp[b-t[i]]) unite(i,mp[b-t[i]]);
else unite(i,0);
}
int A=find(0),B=find(n+1);
if(A==B) printf("NO\n");
else
{
printf("YES\n");
for(int i=1;i<=n;i++)
{
if(find(i)==A)printf("0");
else printf("1");//必须先判断A,因为剩下的不一定
//都已经加入到了B中,存在一些A,B都可以的情况
if(i!=n)printf(" ");
else printf("\n");
}
}
return 0;
}