• D. Binary Spiders 题解(字典树+抽屉原理)


    题目链接

    题目大意

    n个数要你选尽可能多的数使得这些数两两异或>=k 输出你选的所有数 任意一种方案即可

    n 3e5 a[i] 1e9

    题目思路

    听大佬说是经典套路题,感觉很有意思

    下面说下大佬的思路

    假设k的最高位是第i+1位到第29位是独立的

    对于每一组i+1到29位都相同的这些数,由于抽屉原理最多选两个

    然后再看每组是否能用tire选两个即可

    代码写的有点丑,懒得调了

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const int maxn=3e5+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,k,pos=-1;
    int a[maxn];
    map<int,int> mp;
    int cnt=0;
    vector<pair<int,int> > vec[maxn];
    struct trie {
        int nex[maxn*31][2], cnt;
        int exist[maxn*31];  // 该结点结尾的字符串是否存在
        void insert(int x,int id) {  // 插入字符串
            int p = 0;
            for (int i = 29; i>=0; i--) {
                int c = ((x>>i)&1);
                if (!nex[p][c]) nex[p][c] = ++cnt;  // 如果没有,就添加结点
                p = nex[p][c];
            }
            exist[p] = id;
        }
        pair<int,int> find(int x) {  // 查找字符串
            int p = 0;
            int ans=0;
            for (int i = 29; i>=0; i--) {
                int now=((x>>i)&1);
                if(nex[p][!now]){
                    p=nex[p][!now];
                    ans+=(1<<i);
                }else{
                    p=nex[p][now];
                }
            }
            return {ans,exist[p]};
        }
        void clear(){
            for(int i=0;i<=cnt;i++){
                exist[i]=0;
                for(int j=0;j<=1;j++){
                    nex[i][j]=0;
                }
            }
            cnt=0;
        }
    }t;
    signed main(){
        scanf("%d%d",&n,&k);
        for(int i=29;i>=0;i--){
            if(k>=(1<<i)){
                pos=i;
                break;
            }
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            int opt=0,now=a[i];
            for(int j=29;j>=pos+1;j--){
                if(now>=(1<<j)){
                    opt+=(1<<j);
                    now-=(1<<j);
                }
            }
            if(!mp.count(opt)){
                mp[opt]=++cnt;
            }
            vec[mp[opt]].push_back({a[i],i});
        }
        if(k==0){
            printf("%d\n",n);
            for(int i=1;i<=n;i++){
                printf("%d ",i);
            }
            return 0;
        }
        vector<int> pr;
        for(int i=1;i<=cnt;i++){
            t.clear();
            int flag=0;
            for(auto x:vec[i]){
                int val=t.find(x.fi).fi;
                if(val>=k){
                    flag=1;
                    pr.push_back(t.find(x.fi).se);
                    pr.push_back(x.se);
                    break;
                }
                t.insert(x.fi,x.se);
            }
            if(!flag){
                pr.push_back(vec[i][0].se);
            }
        }
        if(pr.size()==1){ //特判
            printf("-1\n");
            return 0;
        }
        printf("%d\n",pr.size());
        for(auto x:pr){
            printf("%d ",x);
        }
        return 0;
    }
    // 3 1 3 2
    
    
    不摆烂了,写题
  • 相关阅读:
    看到关于java资料比较全的,自己收藏
    ie6下pnghack——css方案
    git基本操作
    购物车功能实现
    jquery学习:获取位置position(),offset(),scrollTop困惑
    Datax3.0使用说明
    Scala字符串操作
    Scala中class、object、case class、case object区别
    Scala构造函数
    scala数组操作
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15795753.html
Copyright © 2020-2023  润新知