字典树裸题。之前做过类似的,把代码拿过来提交,居然wa了。调了半天,发现以前的代码,是错的。。。
把每个数字的二进制,扩充到31位,然后插入字典树。对于当前的数,对于他的每一位,每次在树中匹配和他相反的那一位,从高位到低位匹配。最后得到的就是异或最大值。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5+10;
struct MyTrie
{
int next[MAXN*32][2];
int cnt[MAXN*32];
int root,sz;
void init()
{
memset(next,-1,sizeof(next));
memset(cnt,0,sizeof(cnt));
root = sz = 0;
}
void insert(int num)
{
int now = root;
for(int i = 30; i >= 0; --i)
{
int t = (num>>i)&1;
if(next[now][t] == -1)
next[now][t] = ++sz;
cnt[next[now][t]]++;
now = next[now][t];
}
}
void erase(int num)
{
int now = root;
for(int i = 30; i >= 0; --i)
{
int t = (num>>i)&1;
cnt[next[now][t]]--;
int pre = next[now][t];
if(cnt[next[now][t]] == 0)
next[now][t] = -1;
now = pre;
}
}
int query(int num)
{
int ret = 0,t;
int now = root;
for(int i = 30; i >= 0; --i)
{
t = (num>>i)&1;
if(next[now][!t] != -1)
{
t = !t;
ret |= (1<<i);
}
else if(next[now][t] != -1)
ret |= (0<<i);
else
return num;
now = next[now][t];
}
return ret;
}
}Trie;
int main()
{
int q;
scanf("%d",&q);
char op;
int num;
Trie.init();
Trie.insert(0);
while(q--)
{
scanf(" %c %d",&op,&num);
if(op == '+')
Trie.insert(num);
else if(op == '-')
Trie.erase(num);
else
printf("%d\n",Trie.query(num));
}
return 0;
}