Author has gone out of the stories about Vasiliy, so here is just a formal task description.
You are given q queries and a multiset A, initially containing only integer 0. There are three types of queries:
- "+ x" — add integer x to multiset A.
- "- x" — erase one occurrence of integer x from multiset A. It's guaranteed that at least one x is present in the multiset A before this query.
- "? x" — you are given integer x and need to compute the value , i.e. the maximum value of bitwise exclusive OR (also know as XOR) of integer x and some integer y from the multiset A.
Multiset is a set, where equal elements are allowed.
The first line of the input contains a single integer q (1 ≤ q ≤ 200 000) — the number of queries Vasiliy has to perform.
Each of the following q lines of the input contains one of three characters '+', '-' or '?' and an integer xi (1 ≤ xi ≤ 109). It's guaranteed that there is at least one query of the third type.
Note, that the integer 0 will always be present in the set A.
For each query of the type '?' print one integer — the maximum value of bitwise exclusive OR (XOR) of integer xi and some integer from the multiset A.
10 + 8 + 9 + 11 + 6 + 1 ? 3 - 8 ? 3 ? 8 ? 11
11 10 14 13
After first five operations multiset A contains integers 0, 8, 9, 11, 6 and 1.
The answer for the sixth query is integer — maximum among integers , , , and .
题意:n,操作的次数,+ x集合中插入一个元素x;- x集合中删除一个元素x;? x求集合元素中和x异或的最大值是多少
思路:一道01字典树的题。将要插入的数的二进制位倒着建树(为什么?因为异或时高位尽量大,结果才尽量大),即高位在深度低的节点上。用一个数组记录经过各个节点的数的个数,插入时,每经过一个点,将节点的这个值加一,删除时,则减一。查找时,当前节点的这个值大于0,说明有数经过。对于要查找的这个数的高位,如果是1,要使异或值尽量大,那么就要往0的地方走,反之,往1的地方走,实在没办法走,只有按原路径走啦。详见代码。注意:0永远在树中。
ac代码:
#include<bits/stdc++.h> using namespace std; #define Memset(x, a) memset(x, a, sizeof(x)) typedef long long ll; const int maxn = 222222;//集合中的数字个数 int ch[32*maxn][2]; //节点的边信息 ll val[32*maxn]; //节点存储的值 int sz,q; //树中当前节点个数 ll num; void init(){ Memset(ch[0],0); //树清空 sz=1; } void _insert(ll a){ int u=0; for(int i=32;i>=0;i--){ int c=((a>>i)&1); if(!ch[u][c]){ Memset(ch[sz],0); ch[u][c]=sz++; } u=ch[u][c]; ++val[u]; } } void _delete(ll a){ int u=0; for (int i=32; i>=0; --i){ int c=((a>>i)&1); u=ch[u][c]; --val[u]; } } ll query(ll a){ int u=0; ll ans=0; for(int i=32;i>=0;i--){ int c=((a>>i)&1); if (c==1){ if (ch[u][0] && val[ch[u][0]]){ ans+=1<<i; u=ch[u][0]; } else u=ch[u][1]; } else{ if (ch[u][1] && val[ch[u][1]]){ ans+=1<<i; u=ch[u][1]; } else u=ch[u][0]; } } return ans; } int main() { string op; init(); cin>>q; _insert(0); while(q--) { cin>>op>>num; if(op[0]=='+') _insert(num); else if(op[0]=='-') _delete(num); else cout<<query(num)<<endl; } return 0; }