zoukankan      html  css  js  c++  java
  • 【刷题】【cf】 D. Binary Spiders

    Binary Spiders are species of spiders that live on Mars. These spiders weave their webs to defend themselves from enemies.

    To weave a web, spiders join in pairs. If the first spider in pair has xx legs, and the second spider has yy legs, then they weave a web with durability xyx⊕y. Here, ⊕ means bitwise XOR.

    Binary Spiders live in large groups. You observe a group of nn spiders, and the ii-th spider has aiai legs.

    When the group is threatened, some of the spiders become defenders. Defenders are chosen in the following way. First, there must be at least two defenders. Second, any pair of defenders must be able to weave a web with durability at least kk. Third, there must be as much defenders as possible.

    Scientists have researched the behaviour of Binary Spiders for a long time, and now they have a hypothesis that they can always choose the defenders in an optimal way, satisfying the conditions above. You need to verify this hypothesis on your group of spiders. So, you need to understand how many spiders must become defenders. You are not a Binary Spider, so you decided to use a computer to solve this problem.

     
    思路:来自: Codeforces Round #765 (Div. 2)A-D_Arctic_Clam的博客-CSDN博客

    错了一晚上一百天,细节都写在注释里了

    #include<cstdio>
    #include<cstdlib>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0' || c>'9' ) 
        {
            if(c=='-' ) f=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9' ) x=(x<<3)+(x<<1)+c-'0',c=getchar();
        return x*f;
    }
    
    int n,k;
    const int N=3e5+10;
    int a[N],mod=1;
    
    struct node
    {
        int pre,lst,pos;
        bool operator < (const node &a ) const
        { return pre!=a.pre ?pre<a.pre :lst<a.lst ; } //比较lst,顺手少插入一点数据 
    }d[N];
    vector <int > Ans;
    
    int ans;
    int val[32*N],tol;
    int ch[32*N][2];
    void clear()
    {
        ch[0][0]=ch[0][1]=0;//初始化1 
        tol=1;
    }
    void build(int x) 
    {
        int u=0;
        for(int i=30;i>=0;i--) 
        {
            int v=(x>>i)&1;
            if(!ch[u][v]) 
            {
                ch[u][v]=tol; 
                val[tol]=0;//初始化2 
                ch[tol][0]=ch[tol][1]=0; //初始化3 
                tol++; 
            }
            u=ch[u][v]; 
        }
        val[u]=x;
    }
    int query(int x)
    { 
        int u=0;
        for(int i=30;i>=0;i--)
        {
            int v=( (x>>i)&1 ); //?
            if(ch[u][v^1]) u=ch[u][v^1];
            else u=ch[u][v];
        }
        //printf("q:%d %d\n",x,val[u]);
        return val[u]^x;
    }
    void work(int l,int r)
    {
        //printf(" %d %d\n",l ,r );
        if(r==l ) //分三种情况,1只有一个元素 
        {
            ans++;
            //printf("%d\n",ans);
            Ans.push_back(d[l].pos );
            return ;
        }
        
        clear();
        build(d[l].lst );
        for(int i=l+1;i<=r;i++)
            if(d[i].lst !=d[i-1].lst ) //优化减少插入,re改之后ac 
                build(d[i].lst );
        for(int i=l;i<r;i++)
        {
            if(query(d[i].lst ) >=k )//情况2 有两个及以上元素,且最大异或大于等于k 
            {
                for(int j=i+1;j<=r;j++)
                    if((d[i].lst ^ d[j].lst ) >=k )
                    {
                        Ans.push_back(d[i].pos );
                        Ans.push_back(d[j].pos );
                        ans+=2;
                        //printf("%d %d %d\n",ans,d[j].lst,d[i].lst  );
                        return ;
                    }
            }
        }
        ans++;//情况3 即使不满足情况2,也可以找随便一个当作答案
        Ans.push_back(d[l].pos );
        return ;
    }
    
    int main()
    {
        n=read(),k=read();
        while(mod<=k ) mod<<=1;
        for(int i=1;i<=n;i++)
        {
            a[i]=read(); d[i].pos =i;
            d[i].pre =a[i]/mod,d[i].lst =a[i]%mod;
        }
        sort(d+1,d+n+1);
        //分隔且排序 
        
        if(k==0 )//此特例不满足本方法,需要单独处理 
        {
            printf("%d\n",n);
            for(int i=1;i<=n;i++) printf("%d ",i);
            return 0; 
        }
        
        int st=1;
        for(int i=1;i<=n;i++)
            if(d[i].pre !=d[st].pre ) 
                work(st,i-1),st=i;
        work(st,n);
        
        if(ans>=2 )
        {
            printf("%d\n",ans);
            int sz=Ans.size();
            for(int i=0;i<sz;i++)
                printf("%d ",Ans[i]);
        }
        else printf("-1\n");
        return 0;
    } 
  • 相关阅读:
    【题解】Red-Blue Graph Codeforces 1288F 上下界费用流
    【题解】The Magician HDU 6565 大模拟
    HAOI2018游记
    【题解】【THUSC 2016】成绩单 LOJ 2292 区间dp
    【题解】【雅礼集训 2017 Day5】远行 LOJ 6038 LCT
    【题解】Catering World Finals 2015 上下界费用流
    《无问西东...》
    为了世界的和平~一起上caioj~~~!
    新征程~起航!
    bzoj4240: 有趣的家庭菜园(树状数组+贪心思想)
  • 原文地址:https://www.cnblogs.com/xwww666666/p/15805957.html
Copyright © 2011-2022 走看看