Today at the lesson Vitya learned a very interesting function — mex. Mex of a sequence of numbers is the minimum non-negative number that is not present in the sequence as element. For example, mex([4, 33, 0, 1, 1, 5]) = 2 and mex([1, 2, 3]) = 0.
Vitya quickly understood all tasks of the teacher, but can you do the same?
You are given an array consisting of n non-negative integers, and m queries. Each query is characterized by one number x and consists of the following consecutive steps:
- Perform the bitwise addition operation modulo 2 (xor) of each array element with the number x.
- Find mex of the resulting array.
Note that after each query the array changes.
First line contains two integer numbers n and m (1 ≤ n, m ≤ 3·105) — number of elements in array and number of queries.
Next line contains n integer numbers ai (0 ≤ ai ≤ 3·105) — elements of then array.
Each of next m lines contains query — one integer number x (0 ≤ x ≤ 3·105).
For each query print the answer on a separate line.
2 2 1 3 1 3
1 0
4 3 0 1 5 6 1 2 4
2 0 0
5 4 0 1 5 6 7 1 1 4 5
2 2 0 2
题意: 给你一个序列,每次操作使得序列xor x 然后求出未出现的最小的自然数。
思路: 条件1 : 一个数 num xor x1, 然后再 xor x2 和num xor(x1 xor x2) 是相同的。
条件2 : x xor y =z 那么z xor y =x 是一定并且唯一的。
所以我们可以把问题转化为求0到6e5 中未出现的数 和 x xor 的最小值。 至于6e5 是因为要多出一位,例如给你序列为 1到3e5 ,就需要将字典树的深度多加一。
代码:
#include<bits/stdc++.h>
using namespace std;
#define Memset(x, a) memset(x, a, sizeof(x))
typedef long long ll;
const int maxn = 6e5 + 5;//集合中的数字个数
int ch[21*maxn][2]; //节点的边信息
ll val[21*maxn]; //节点存储的值
int sz; //树中当前节点个数
//int num[32*maxn];
void init(){
Memset(ch[0],0); //树清空
//memset(num,0,sizeof(num));
sz=1;
}
void _insert(ll a){//在字典树中插入 a
//和一般字典树的操作相同 将X的二进制插入到字典树中
int rt=0;
for(int i=32;i>=0;i--){
int c=((a>>i)&1);
if(!ch[rt][c]){
Memset(ch[sz],0);
val[sz]=0;
//num[sz]=0;
ch[rt][c]=sz++;
}
rt=ch[rt][c];
//num[rt]++;
}
val[rt]=a; //最后的节点插入value
}
ll query(ll a){ //在字典树中查找和a异或的值最小的元素b 返回b的值
int rt=0;
for(int i=32;i>=0;i--){
int c=((a>>i)&1);
if(ch[rt][c]/*&&num[ch[rt][c]]*/) rt=ch[rt][c]; // 注意这里的含义 c=0,b=c,b^c=0; c=1; b=c; b^c=0;
else rt=ch[rt][c^1];
}
return val[rt]^a;
}
int n,m;
int a[maxn];
int vis[maxn*2];
int main()
{
cin>>n>>m;
init();
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
vis[a[i]]=1;
}
for(int i=0;i<=6e5;i++)
{
if(vis[i]==0){
_insert((ll)i);
}
}
ll tmp=0;
ll x;
while(m--)
{
cin>>x;
tmp=tmp^x;
ll ans=query(tmp);
cout<<ans<<endl;
}
return 0;
}