您的位置:首页 > 其它

codeforces 706D. Vasiliy's Multiset 带删除操作的字典树(真模版)

2016-08-13 16:07 711 查看
D. Vasiliy's Multiset

time limit per test
4 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

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.

Input
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.

Output
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.

Example

Input
10
+ 8
+ 9
+ 11
+ 6
+ 1
? 3
- 8
? 3
? 8
? 11


Output
11
10
14
13


Note
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
[2];  ///存放这棵字典树
int sz;        ///结点编号
int ans;       ///答案
int val
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  字典树