题目传送门 : http://codeforces.com/contest/706/problem/D
题意:给n组操作(n<=100000),操作有三种:
1、‘+’ 在集合中加一个数x
2、‘-’ 在集合中减一个数x
3、‘?’问x与集合中任意一个数XOR的最大值是多少
该集合中恒有0,且集合中元素可以重复
思路:一开始我并不会01字典树这种东西,然后想了很多奇怪的方法,感觉都不行。最后看了题解,学了一发01字典树。
建一个带删除操作的01字典树即可
下面分别给一个静态节点和一个动态节点构造01字典树的代码。
静态的代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stdio.h>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <bitset>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
#define ull unsigned long long
#define mem(n,v) memset(n,v,sizeof(n))
#define MAX 200005
#define MAXN 200005
#define PI 3.1415926
#define E 2.718281828459
#define opnin freopen("text.in.txt","r",stdin)
#define opnout freopen("text.out.txt","w",stdout)
#define clsin fclose(stdin)
#define clsout fclose(stdout)
#define haha1 cout << "haha1"<< endl
#define haha2 cout << "haha2"<< endl
#define haha3 cout << "haha3"<< endl
const int INF = 0x3f3f3f3f;
const ll INFF = 0x3f3f3f3f3f3f3f3f;
const double pi = 3.141592653589793;
const double inf = 1e18;
const double eps = 1e-8;
const ll mod = 1e9+7;
const ull mx = 133333331;
/**************************************************************************/
struct edge
{
int to,num;
}ch[32*MAX][2];
ll val[32*MAX];
int sz;
void init(){
mem(ch[0],0);
mem(val,0);
sz=1;
}
void inser(ll a){
int u=0;
for(int i=32;i>=0;i--){
int c=((a>>i)&1);
if(!ch[u][c].to){
mem(ch[sz],0);
val[sz]=0;
ch[u][c].to=sz++;
}
ch[u][c].num++;
u=ch[u][c].to;
}
val[u]=a;
}
ll query(ll a){
int u=0;
for(int i=32;i>=0;i--){
int c=((a>>i)&1);
if(ch[u][c^1].to) u=ch[u][c^1].to;
else u=ch[u][c].to;
}
return val[u];
}
void del(ll a){
int c= 0,u =0,temp = 0;
for(int i=32;i>=0;i--){
c =((a>>i)&1);
ch[u][c].num--;
temp = u;
u = ch[u][c].to;
if(!ch[temp][c].num) ch[temp][c].to = 0;
}
if(!ch[temp][c].to) val[u] = 0;
}
int main()
{
int n;
cin >> n;
init();
getchar();
for(int i=1;i<=n;i++){
char x;
int y;
x = getchar();
getchar();
scanf("%d",&y);
getchar();
inser(0);
if(x == '+') inser(y);
else if(x == '-') del(y);
else printf("%I64d\n",query(y)^y);
}
}
动态的代码如下:
#include <algorithm>
#include <bitset>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <climits>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
struct trieNode
{
trieNode *to[2];
int num;
int val;
trieNode(int num = 0, int val = 0) : num(num), val(val) {
memset(to,0, sizeof(to));
}
};
void inser(int a, trieNode *u){
for(int i=31;i>=0;i--){
int c = ((a>>i)&1);
if(u->to[c] == NULL){
u->to[c] = new trieNode();
}
(u->to[c])->num++;
u = u->to[c];
}
u->val = a;
}
int query(int a,trieNode *u){
for(int i=31;i>=0;i--){
int c=((a>>i)&1);
if(u->to[c^1] )
u = u->to[c^1];
else
u = u->to[c];
if(u == NULL)
return 0L;
}
return u -> val;
}
void clear(trieNode *u){
if(u -> to[0])
clear(u -> to[0]);
if(u -> to[1])
clear(u -> to[1]);
free(u);
}
void del(long long a, trieNode *u){
int c= 0;
trieNode *temp, *cur = NULL;
for(int i=31;i>=0;i--){
if(u == NULL)
return;
c =((a>>i)&1);
(u ->to[c]) -> num--;
temp = u;
u = u->to[c];
if(cur){
free(cur);
cur = NULL;
}
if((temp -> to[c]) -> num <= 0){
temp -> to[c] = NULL;
cur = temp -> to[c];
}
}
if(cur)
free(cur);
}
int main()
{
int n;
cin >> n;
trieNode* root = new trieNode();
for(int i=1;i<=n;i++){
char x;
int y;
getchar();
x = getchar();
scanf("%d",&y);
inser(0,root);
if(x == '+') inser(y,root);
else if(x == '-') del(y,root);
else printf("%d\n",query(y,root)^y);
}
clear(root);
}