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
.
题意:
一共有三种操作,+为往多重集里面加入x,-为从多重集里面删除x,?则是从多重集中选出一个数来与x异或使得值最大。
思路:
用01字典树,从高位往地位存入二进制。注意要记录下每个节点出现的次数,因为还有删除操作。
异或的时候取和x当前位的相反就行了,这样才能保证异或出来的最大。
坑点:0一直在多重集里,所以每次都加入0,则一定保证0在多重集合里面了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=2e5+5;
int cnt,root;
struct node
{
int next[2];
int num;
}q[40*maxn];
void in(int root,int n)
{
for(int i=30;i>=0;i--)
{
int x=(n>>i)&1;
if(q[root].next[x]==0)
{
q[root].next[x]=++cnt;
q[q[root].next[x]].num++;
}
else
{
q[q[root].next[x]].num++;
}
root=q[root].next[x];
}
}
void del(int root,int n)
{
for(int i=30;i>=0;i--)
{
int x=(n>>i)&1;
if(q[q[root].next[x]].num>0)
q[q[root].next[x]].num--;
root=q[root].next[x];
}
}
int query(int root,int n)
{
int ans=0;
for(int i=30;i>=0;i--)
{
ans<<=1;
int x=(n>>i)&1;
if(q[q[root].next[!x]].num!=0)
{
ans=ans|(!x);
root=q[root].next[!x];
}
else
{
ans=ans|x;
root=q[root].next[x];
}
}
return ans^n;
}
int main()
{
int t,x;
char op[5];
while(~scanf("%d",&t))
{
cnt=0,root=0;
memset(q,0,sizeof(q));
for(int i=1;i<=t;i++)
{
scanf("%s",op);
scanf("%d",&x);
in(root,0);
if(op[0]=='+')
{
in(root,x);
}
else if(op[0]=='-')
{
del(root,x);
}
else
{
printf("%d\n",query(root,x));
}
}
}
return 0;
}