【题解】
如果题目没看懂就看一下上面那个note的样例解释嘛。应该知道是什么意思了吧。
然后我把样例的前6个操作数的二进制列举一下。
如果不足4位就前面补0
1000
1001
1011
0110
0001
询问0011
思路是这样的
把前面5个数字加入字典树中。
然后从根节点开始。看到询问的二进制第一位是0.
0的话xor什么最好呢?当然是1.
那就看看从根节点往下有没有一个1有就往下走,没有的话就走0(0是一直存在的。所以肯定可以走);然后二进制的第二位也以此类推。
最后我们走到底的肯定是最大值。
这里涉及到一个原理就是
(二进制)
1000 > 0111
即2^x > 2^(x-1)+2^(x-2) + ...+ 2^0
实际上左边那个等于右边加1.
节点加入和删除的话
给每个节点都设置一个值。走到这个点就增加一下这个节点的值。然后要删除的时候仍旧走一遍这个路。然后递减路上走过的节点的值。
这3个操作其实很像的。
然后10^9 二进制的长度为30
【代码】
#include <cstdio> const int MAX_SIZE = 7000000; int q, v[MAX_SIZE][2] = { 0 }, totn = 0, num[MAX_SIZE] = { 0 }; int a[40]; //v[t][0],v[t][1]分别表示t的左右儿子,左儿子代表0 void add(int x) { int temp = 0, temp1 = x; a[0] = 30; while (temp1 > 0) //从后往左加入二进制各个位 { a[a[0]] = temp1 & 1; temp1 = temp1 >> 1; a[0]--; } for (int i = 1; i <= a[0]; i++)//1..a[0]是补0 { if (v[temp][0] == 0) v[temp][0] = ++totn; temp = v[temp][0]; num[temp]++; } for (int i = a[0] + 1; i <= 30; i++)//a[0]+1..30才是这个数的二进制 { if (v[temp][a[i]] == 0) v[temp][a[i]] = ++totn; temp = v[temp][a[i]]; num[temp]++; } } void de_lete(int x) { int temp = 0, temp1 = x; a[0] = 30; while (temp1 > 0) { a[a[0]] = temp1 & 1; temp1 = temp1 >> 1; a[0]--; } for (int i = 1; i <= a[0]; i++) { temp = v[temp][0]; num[temp]--; } for (int i = a[0] + 1; i <= 30; i++) { temp = v[temp][a[i]]; num[temp]--; } } int query(int x) { int temp = 0, temp1 = x; a[0] = 30; while (temp1 > 0) { a[a[0]] = temp1 & 1; temp1 = temp1 >> 1; a[0]--; } int leijia = 0; for (int i = 1; i <= a[0]; i++) if (v[temp][1] != -1 && num[v[temp][1]] > 0) { temp = v[temp][1]; leijia += 1 << (30 - i); //代表2^(30-i) } else temp = v[temp][0]; for (int i = a[0] + 1; i <= 30; i++) if (v[temp][1 - a[i]] != -1 && num[v[temp][1 - a[i]]] > 0) { temp = v[temp][1 - a[i]]; leijia += 1 << (30 - i); } else temp = v[temp][a[i]]; return leijia; } void input_data() { scanf("%d", &q); for (int i = 1; i <= q; i++) { char op[5]; int x; scanf("%s%d", op, &x); if (op[0] == '+') add(x); else if (op[0] == '-') de_lete(x); else printf("%d ", query(x)); } } int main() { //freopen("F:\rush.txt", "r", stdin); add(0); input_data(); return 0; }