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

posted @ 2022-01-12 23:02  hunxuewangzi  阅读(142)  评论(0编辑  收藏  举报