题目大意:
给出一个数组,每次操作将整个数组亦或一个数x,问得到的数组的结果中的mex.mex表示为自然数中第一个没有出现过的数。
思路:
我们可以转化为求没出现的数中的最小值。
我们既然这道求亦或最大值,那么一定可以求亦或最小值, 这个和亦或最大值有着相同的思路。
题目是给多个值亦或。我们没有必要改变trie树中数,直接把要亦或的值亦或起来。
至于trie树中的值。,我们要存入不是题目中给的那些数。
#include <bits/stdc++.h>
#define mem(x,v) memset(x,v,sizeof(x))
#define go(i,a,b) for (int i = a; i <= b; i++)
#define og(i,a,b) for (int i = a; i >= b; i--)
using namespace std;
typedef long long LL;
const double EPS = 1e-10;
const int INF = 0x3f3f3f3f;
const int N = 6e5+10;
int Ac[N*21][2];
int cnt;
bool vis[21*N];
void Insert(int z){
int now = 0;
og(i,20,0){
int id = (z & (1 << i))?1:0;
if (!Ac[now][id]) Ac[now][id] = ++cnt;
now = Ac[now][id];
}
}
int Find(int z){
int now = 0,ans = 0;
og(i,20,0){
int id = (z & (1<<i))?1:0;
if (!Ac[now][id]) {
id ^= 1;
ans = ans | (1 << i);
}
now = Ac[now][id];
}
return ans;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
go(i,1,n){
int x;
scanf("%d",&x);
vis[x] = 1;
}
go(i,0,600100){
if (!vis[i]) Insert(i);
}
int z = 0;
go(i,1,m){
int x;
scanf("%d",&x);
z = z ^ x;
int ans = Find(z);
printf("%d\n",ans);
}
return 0;
}