版权声明:欢迎转载 https://blog.csdn.net/yandaoqiusheng/article/details/89282790
题目链接:传送门
给出一个序列,m次操作每次给出一个数x,让序列中的所有数都异或上x,求每次操作完后的序列mex(最小未出现自然数)
会01trie就简单了
把序列去重后加到01trie中
统计每个子树下有多少个数
查询时左儿子满了就往右走,右儿子同理
直到走到空节点就直接返回
一定注意一开始存一个根节点
也就是cnt一开始一定为1
/**
* @Date: 2019-04-13T10:54:44+08:00
* @Last modified time: 2019-04-13T14:16:27+08:00
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define A 3000010
#define B 2010
using namespace std;
typedef long long ll;
int siz[A], ch[A][2], n, m, a[A], b, s, cnt = 1;
void insert(int x, int fr = 1) {
for (int i = 20; i > 0; i--) {
siz[fr]++;
if (x & (1 << (i - 1))) {
if (!ch[fr][1]) ch[fr][1] = ++cnt;
fr = ch[fr][1];
}
else {
if (!ch[fr][0]) ch[fr][0] = ++cnt;
fr = ch[fr][0];
}
}
siz[fr]++;
}
int ask(int fr = 1, int ans = 0) {
for (int i = 20; i > 0; i--)
if (s & (1 << (i - 1))) {
if (!ch[fr][1]) return ans;
else if (siz[ch[fr][1]] < (1 << (i - 1))) fr = ch[fr][1];
else fr = ch[fr][0], ans += (1 << (i - 1))
}
else {
if (!ch[fr][0]) return ans;
else if (siz[ch[fr][0]] < (1 << (i - 1))) fr = ch[fr][0];
else fr = ch[fr][1], ans += (1 << (i - 1));
}
return ans;
}
int main(int argc, char const *argv[]) {
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
n = unique(a + 1, a + n + 1) - a - 1;
for (int i = 1; i <= n; i++) insert(a[i]);
while (m--) {
cin >> b; s ^= b;
cout << ask() << endl;
}
return 0;
}