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 将集合中的x元素删除,? x,询问集合中与x异或的最大值。
集合中相同元素只需要插入一次就行了,用一个map来维护一下集合中相同元素的个数,删除同理。
字典树模版,带删除。
#include <bits/stdc++.h>
using namespace std;
const int N = 5000000+10;
int ch[N][2]; ///存放这棵字典树
int sz; ///结点编号
int ans; ///答案
int val[N];
map<int,int> mp;
void Init() ///初始化
{
sz = 1;
ans = 0;
memset(ch,0,sizeof ch);
}
void inssert(int num){ ///在字典树中插入一个数字
int u = 1;
val[u]++;
for(int i = 30;i >= 0;i--){
int c = (num>>i)&1;
if(!ch[u][c]){
ch[u][c] = ++sz;
}
u = ch[u][c];
val[u]++;
}
}
void lookfor(int num) ///字典树中查找num的异或最大值
{
int u = 1;
ans = 0;
for(int i = 30;i >= 0;i--){
int c = num&(1<<i);
if(c) c = 1;
if(val[ch[u][!c]]){ ///根据是否标记进行查找
ans |= (1<<i);
u = ch[u][!c];
}
else u = ch[u][c];
}
}
void erasee(int num) ///删除就对标记的val--就行了
{
int u = 1;
val[u]--;
for(int i = 30;i >= 0;i--){
int t = num&(1<<i);
int c;
if(t) c = 1;
else c = 0;
if(c == 0) u = ch[u][0];
else u = ch[u][1];
val[u]--;
}
}
int main()
{
Init();
int q;
scanf("%d",&q);
while(q--){
inssert(0);
char s[2];
int x;
scanf("%s%d",s,&x);
if(s[0] == '+'){
mp[x]++;
if(mp[x] == 1)
inssert(x);
}
if(s[0] == '?'){
lookfor(x);
printf("%d\n",ans);
}
if(s[0] == '-'){
mp[x]--;
if(mp[x] == 0){
erasee(x);
}
}
}
return 0;
}