题目:http://codeforces.com/problemset/problem/706/D
题意:
+表示吧这个数加到集合中,-表示把这个数从集合中减去一次,?表示集合里面的一个y使的x^y最大
分析:
要使异或最大,那么尽量从高位使两个数不同即可。
Trie树。
#include<bits/stdc++.h>
using namespace std;
const int N=1e7+9;
int a[N][2],cal[N];
int tot;
void add(int x,int y) //插入或删除一个元素
{
int cur=0;
for(int i=31;i>=0;i--){
int t=(x>>i)&1;
if(!a[cur][t])a[cur][t]=tot++;
cur=a[cur][t];
cal[cur]+=y;
}
}
int query(int x)
{
int cur=0,ans=0;
for(int i=31;i>=0;i--){
int t=(x>>i)&1;
if(cal[a[cur][t^1]]){
ans+=(1<<i);
cur=a[cur][t^1];
}
else cur=a[cur][t];
}
return ans;
}
int main()
{
int n,x;
char op;
tot=1;
add(0,1);
scanf("%d",&n);
for(int i=0;i<n;i++){
cin>>op>>x;
if(op=='+'){
add(x,1);
}
else if(op=='-'){
add(x,-1);
}
else{
printf("%d\n",query(x));
}
}
return 0;
}
/*
Input
10
+ 8
+ 9
+ 11
+ 6
+ 1
? 3
- 8
? 3
? 8
? 11
Output
11
10
14
13
*/
或者可以直接用multiset模拟:
#include<bits/stdc++.h>
using namespace std;
const int N=1e7+9;
int main()
{
int n,x;
char op;
multiset<int>s;
s.insert(0);
scanf("%d",&n);
for(int i=0;i<n;i++){
cin>>op>>x;
if(op=='+'){
s.insert(x);
}
else if(op=='-'){
s.erase(s.find(x));
}
else{
int ans=0;
for(int i=31;i>=0;i--){
ans|=(~x&(1<<i));
multiset<int>::iterator it=s.lower_bound(ans);
if(it==s.end()||*it>=ans+(1<<i)){
// cout<<ans<<endl;
ans^=1<<i;
}
}
printf("%d\n",x^ans);
}
}
return 0;
}