Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset(可持久化Trie)

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:

  1. "+ x" — add integer x to multiset A.
  2. "- 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.
  3. "? 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 089116 and 1.

The answer for the sixth query is integer  — maximum among integers and .


 

 

题目链接:CF 706D

字典树水题,只是最近在膜可持久化字典树,拿这道题当模版写了一下,感觉跟主席树非常像,毕竟都是可持久化的思想,新建节点信息代替更改节点信息,写法也简单明了如果会主席树的话代码是不难理解的,只是最后返回的值是异或过的值,因为一个节点不再是模拟地去初始化、连接到链表尾,而是直接把节点的位置拿来标记为已使用,把信息复制到对应节点上去,因此需要一个变量cnt来记录这条路径有没有被覆盖过或者说有没有被使用过,有的话说明这条路到底是存在一个数,即用普通字典树的话来说就是这个点不为NULL,可以往下走。滋瓷范围内的Xor最大值的贪心查询

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=200010;
struct Trie
{
	int nxt[2];
	int cnt;
};
Trie L[N*34];
int tot;
int root[N];

void init()
{
	memset(L,0,sizeof(L));
	tot=0;
}
void update(int &cur,int ori,int step,int n,int v)
{
	cur=++tot;
	L[cur]=L[ori];
	L[cur].cnt+=v;
	if(step<0)
		return ;
	int t=(n>>step)&1;
	update(L[cur].nxt[t],L[ori].nxt[t],step-1,n,v);
}
int Find(int S,int E,int step,int n)
{
	if(step<0)
		return 0;
	int t=(n>>step)&1;
	if(L[L[E].nxt[t^1]].cnt-L[L[S].nxt[t^1]].cnt>0)
        return (1<<step)+Find(L[S].nxt[t^1],L[E].nxt[t^1],step-1,n);
	else
		return Find(L[S].nxt[t],L[E].nxt[t],step-1,n);
}
int main(void)
{
	int n,x,i;
	char ops[3];

	while (~scanf("%d",&n))
	{
		init();
		update(root[1],root[0],31,0,1);
		int op=1;
		int sz=0;
		for (i=1; i<=n; ++i)
		{
			scanf("%s",ops);
			if(ops[0]=='+')
			{
				++sz;
				++op;
				scanf("%d",&x);
				update(root[op],root[op-1],31,x,1);
			}
			else if(ops[0]=='-')
			{
				--sz;
				++op;
				scanf("%d",&x);
				update(root[op],root[op-1],31,x,-1);
			}
			else
			{
				scanf("%d",&x);
				if(!sz)
				{
					printf("%d\n",x);
					continue;
				}
				printf("%d\n",Find(root[0],root[op],31,x));
			}
		}
	}
}
posted @ 2016-11-30 22:19  Blackops  阅读(351)  评论(0编辑  收藏  举报