Codeforces 842D

题意

给出一个有n个元素的数组,之后有m组询问,把那个数组里的所有元素都xor询问给出的数字,问最小的不在数组中的自然数。第二组询问的时候数组里的所有元素都已经xor第一组询问给出的数,以此类推。

题解

很典型的利用字典树求xor最值问题。只要根据01建出字典树就很好做了。

#include<cstdio>
#include<cstring>
struct node{
     node *child[2]={NULL};//开了c++11所以可以这么做
     int val;
};
node *root;
bool pd[600005],s[22];
int n,m,c,d;
void change(int a){
     int jis=0;
     bool pd[22]={0};//c++11
     while(a) pd[++jis]=a%2,a/=2;
     if(!pd[jis]) pd[++jis]=1;
     for(int i=1;i<=20;++i)
        s[i]=pd[21-i];
}
void update(node* &cur,int len,int p,int val){
     if(p>len) return (void)(cur->val=val);
     if(!cur->child[s[p]]) cur->child[s[p]]=new node;
     update(cur->child[s[p]],len,p+1,val);
}
void query(node* &cur,int len,int p,int val){
     if(p>len) return (void)printf("%d\n",cur->val^val);
     if(cur->child[s[p]]) query(cur->child[s[p]],len,p+1,val);//查询的时候贪心
     else query(cur->child[1-s[p]],len,p+1,val);
}
int main(){
     root=new node;
     scanf("%d%d",&n,&m);
     while(n--) scanf("%d",&c),pd[c]=1;
     if(!pd[0]){
        memset(s,0,sizeof s);
        update(root,20,1,0);
    }
     for(int i=1;i<=6e5;++i) if(!pd[i]) change(i),update(root,20,1,i);
     while(m--){
          scanf("%d",&c);
          d^=c;
          if(d==0) memset(s,0,sizeof s);else
        change(d);
          query(root,20,1,d);
     }
     return 0;
}

猜你喜欢

转载自www.cnblogs.com/jiaangk/p/9203789.html