分析
首先,由于异或满足结合律
所以我们可以把每次需要异或的值异或起来
在原01Trie树上找即可
接下来,我们看一下如何找
由于我们需要的是最小的
所以我们每次走到一个节点的时候
不能走,当且仅当这颗子树是满的
所以我们可以依据这个性质走即可
时间复杂度:
代码
//CF842D
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define Cl(X,Y) memset((X),(Y),sizeof(X))
#define FOR(i,A,B) for(int i=A;i<=B;i++)
#define BOR(i,A,B) for(int i=A;i>=B;i--)
#define Debug(X) cerr<<#X<<" = "<<X<<" "
#define Lowbit(X) (X & (-X))
#define Skip cout<<endl;
#define INF 0x3f3f3f3f
#define Mod 998244353
#define Rson (X<<1|1)
#define Lson (X<<1)
using namespace std;
typedef long long ll;
const int N = 3e5+5;
vector<int>a;
int son[N*20][2], sz[N*20], cnt, root;
inline int newnode() { return ++cnt; }
inline void init() {
cnt = 0;
root = newnode();
}
inline void insert(int x) {
int p = root;
for(int i = 19; i >= 0; --i) {
if(x&(1<<i)) {
if(son[p][1] == 0) son[p][1] = newnode();
p = son[p][1];
sz[p]++;
} else {
if(son[p][0] == 0) son[p][0] = newnode();
p = son[p][0];
sz[p]++;
}
}
}
int p2[25];
int query(int x) {
int p = root, res = 0;
for(int i = 19; i >= 0; --i) {
if(x&(1<<i)) {
if(sz[son[p][1]] != p2[i]) {
p = son[p][1];
res |= (1<<i);
} else {
p = son[p][0];
}
} else {
if(sz[son[p][0]] != p2[i]) {
p = son[p][0];
} else {
res |= (1<<i);
p = son[p][1];
}
}
}
return res^x;
}
int main() {
p2[0] = 1;
FOR(i,1,24) p2[i] = p2[i-1]*2;
int n, m;
scanf("%d %d", &n, &m);
FOR(i,1,n) {
int x;
scanf("%d", &x);
a.emplace_back(x);
}
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
for(int x : a) { insert(x); }
int now = 0;
FOR(i,1,m) {
int x;
scanf("%d", &x);
now ^= x;
printf("%d\n", query(now));
}
return 0;
} 
京公网安备 11010502036488号