题意
给出一个有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;
}