题目链接:http://codeforces.com/contest/842/problem/D
题意:定义Mex为一个序列中最小的未出现的正整数,给定一个长度为n的序列,然后有m个询问,每个询问给定一个数x,先对序列每个数与x进行异或运算(^),之后输出当前序列修改完之后的Mex。
思路:因为对于原序列和x异或后,得到的新序列再与y异或相当于原序列与z(z=x^y)进行异或,所以问题就可以转化为对于一个数val,原序列和val进行异或后得到新序列的Mex是多少? 考虑01字典树,先把序列的n个数插入字典树(相同的数只插一次),考虑现在的val=0,那么如果左子树(边权为0的边)没有满,说明Mex在左子树,否则在右子树,直到最后到叶子结点为止,那么答案就是该叶子所代表的权值。 现在考虑val为任意数,对于val的二进制为0的位,按照上面的分析即可,但是对于二进制为1的位,优先走右子树(边权为1的边,因为1^1=0, 1^0=1,所以对于右子树相当于异或后的左子树, 左子树相当于异或后的右子树), 一直到叶子结点为止。
#define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<stdio.h> #include<queue> #include<vector> #include<stack> #include<map> #include<set> #include<time.h> #include<cmath> #include<sstream> #include<assert.h> using namespace std; typedef long long int LL; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3fLL; const int MAXN = 3e5 + 24; struct Trie{ int val[MAXN << 4]; int next[MAXN << 4][2]; int root, L; int newnode(){ next[L][0] = next[L][1] = -1; val[L] = 0; return L++; } void init(){ L = 0; root = newnode(); build(0,0); } void build(int u,int deep){ if (deep == 19){ return; } next[u][0] = newnode(); next[u][1] = newnode(); build(next[u][0], deep + 1); build(next[u][1], deep + 1); } void insert(int x){ int now = root; for (int i = 18; i >= 0; i--){ int num = (1 << i)&x ? 1 : 0; now = next[now][num]; val[now]++; } } int Query(int x){ int now = root, res = 0; for (int i = 18; i >= 0; i--){ int num = (1 << i)&x ? 1 : 0; if (val[next[now][num]] < (1 << i)){ //异或后0的边 now = next[now][num]; } else{ //异或后1的边, 顺便把权值累计 now = next[now][!num]; res |= (1 << i); } } return res; } }trie; set<int>se; int main(){ #ifdef kirito freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif int start = clock(); int n, m,val; while (~scanf("%d%d", &n, &m)){ int prexor = 0; trie.init(); se.clear(); for (int i = 1; i <= n; i++){ scanf("%d", &val); if (!se.count(val)){ trie.insert(val); } se.insert(val); } for (int i = 1; i <= m; i++){ scanf("%d", &val); prexor ^= val; printf("%d ", trie.Query(prexor)); } } #ifdef LOCAL_TIME cout << "[Finished in " << clock() - start << " ms]" << endl; #endif return 0; }