Codeforces Round #268 (Div. 2) D

快哭晕了。。。。自己简直是作死作到不能再死。。。。

他说是2-SAT。。。看了题就用2-SAT敲。。。。最后交一发。。。居然WA在TEST1。。。。。然后没时间了= =。。。今天发现输出0,1哪里位运算打反了。。。。(<<1打成了>>1.。。)。。。

A表示在A集合,A'表示在B集合。。。。

把输入的数用map存下,并标号。。。然后再遍历一遍输入的数。

aa=a-x[i],bb=b-x[i]..如果能在map中找打aa,说明输入了aa,所以当前x[i]在集合B的话,aa就一定在集合B,aa在集合A,x[i]就一定要在集合A。。。就是A'-B',B-A(A表示x[i],B表示aa)不存在就x[i]一定在集合A。。A'-A..

在map中能找到bb,x[i]在集合A,bb就一定在集合A,bb在集合B,x[i]就一定在集合B,就是A-B,B'-A',同理不存在x[i]在集合B。。A-A'。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<string>
#include<map>
#include<vector>
#define ll __int64
using namespace std;
const int MAXN=200010;
vector<int> G[MAXN];
map<ll,int> mp;
int x[MAXN];
int sccno[MAXN],low[MAXN],pre[MAXN],sc_cnt,dfs_clock;
stack<int> S;
void init()
{
    memset(pre,0,sizeof(pre));
    memset(sccno,0,sizeof(sccno));
    sc_cnt=dfs_clock=0;
}
void tarjan(int u)
{
    low[u]=pre[u]=++dfs_clock;
    S.push(u);
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(!pre[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!sccno[v])
            low[u]=min(low[u],pre[v]);
    }
    if(low[u]==pre[u])
    {
        sc_cnt++;
        while(1)
        {
            int x=S.top();
            S.pop();
            sccno[x]=sc_cnt;
            if(x==u)
                break;
        }
    }
}
bool find_sc(int n)
{
    init();
    for(int i=0;i<2*n;i++)
    {
        if(!pre[i])
            tarjan(i);
    }
    for(int i=0;i<n;i++)
    {
        if(sccno[i<<1]==sccno[i<<1|1])
            return 0;
    }
    return 1;
}
int main()
{
    int n,a,b,i,j;
    string s1;
    while(scanf("%d%d%d",&n,&a,&b)==3)
    {
        mp.clear();
        for(i=0;i<=2*n;i++)
            G[i].clear();
        for(i=0;i<n;i++)
        {
            scanf("%d",&x[i]);
            mp[x[i]]=i;
        }
        for(i=0;i<n;i++)
        {
            int aa=a-x[i];
            int bb=b-x[i];
            if(mp.count(aa))
            {
                int k=mp[aa];
                G[i<<1|1].push_back(k<<1|1);
                G[k<<1].push_back(i<<1);
            }
            else
            {
                G[i<<1|1].push_back(i<<1);
            }
            if(mp.count(bb))
            {
                int k=mp[bb];
                G[i<<1].push_back(k<<1);
                G[k<<1|1].push_back(i<<1|1);
            }
            else
            {
                G[i<<1].push_back(i<<1|1);
            }
        }
        bool flag=find_sc(n);
        if(flag)
        {
            printf("YES\n");
            for(i=0;i<n;i++)
            {
                if(sccno[i<<1]>=sccno[i<<1|1])
                {
                    printf("0");
                }
                else
                    printf("1");
                if(i!=n-1)
                    printf(" ");
                else
                    printf("\n");
            }
        }
        else
            printf("NO\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值