CF706D Vasiliy‘s Multiset

3 篇文章 0 订阅

Author has gone out of the stories about Vasiliy, so here is just a formal task description.

You are given qq queries and a multiset AA , initially containing only integer 00 . There are three types of queries:

  1. "+ x" — add integer xx to multiset AA .
  2. "- x" — erase one occurrence of integer xx from multiset AA . It's guaranteed that at least one xx is present in the multiset AA before this query.
  3. "? x" — you are given integer xx and need to compute the value 

    , i.e. the maximum value of bitwise exclusive OR (also know as XOR) of integer xx and some integer yy from the multiset AA .

Multiset is a set, where equal elements are allowed.

题意:刚开始a集合里有一个数0,那么我们有q个操作:1.+x,将x加到集合a中,2.-x,将x从集合中减掉,3.?x,输出集合a中的数与x的最大异或值

思路:异或的话存二进制字典树,对插入操作就是平常的操作,因为还有一个删除和询问所以我们需要用个num数组记录一下一个数的二进制每个位的数的个数,删除的时候遍历一下num--,因为有询问操作所以我们要用一个数组v来记录一下到一个编号的数是多少

/*

 .----------------.  .----------------.  .----------------.  .----------------. 
| .--------------. || .--------------. || .--------------. || .--------------. |
| |  ________    | || |  _________   | || | ____    ____ | || |     ____     | |
| | |_   ___ `.  | || | |_   ___  |  | || ||_   \  /   _|| || |   .'    `.   | |
| |   | |   `. \ | || |   | |_  \_|  | || |  |   \/   |  | || |  /  .--.  \  | |
| |   | |    | | | || |   |  _|  _   | || |  | |\  /| |  | || |  | |    | |  | |
| |  _| |___.' / | || |  _| |___/ |  | || | _| |_\/_| |_ | || |  \  `--'  /  | |
| | |________.'  | || | |_________|  | || ||_____||_____|| || |   `.____.'   | |
| |              | || |              | || |              | || |              | |
| '--------------' || '--------------' || '--------------' || '--------------' |
 '----------------'  '----------------'  '----------------'  '----------------'

*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<deque>
#include<cmath>
#include<stack>
#define int long long
#define lowbit(x) x&(-x)
#define PI 3.1415926535
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int gcd(int a,int b){
	return b>0 ? gcd(b,a%b):a;
}
/*
int dx[8]={-2,-2,-1,1,2,2,-1,1};
int dy[8]={-1,1,2,2,1,-1,-2,-2};
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
int dx[8]={-1,1,0,0,-1,-1,1,1};
int dy[8]={0,0,-1,1,-1,1,-1,1};
*/
//int e[N],ne[N],h[N],idx,w[N];
/*void add(int a,int b,int c){
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
*/
const int N=2e5+10;
int n;
int cnt;
int tr[N*17][2],num[N*27],v[N*27];//v是记录每个编号所表示的数字
void insert(int x){
	int p=0;
	for(int i=32;i>=0;i--){
		int op=x>>i&1;
		if(!tr[p][op]){
			tr[p][op]=++cnt;
		}
		p=tr[p][op];
		num[p]++;//对于每个位上的二进制数的编号,个数++
	}
	v[p]=x;//到最后的时候记录一下到达这个编号所表示的值
}
void declear(int x){//删除的是x的每一位二进制的数的编号的个数
	int p=0;
	for(int i=32;i>=0;i--){
		int op=x>>i&1;
		p=tr[p][op];
		num[p]--;
	}
}
int query(int x){
	int p=0;
	for(int i=32;i>=0;i--){
		int op=x>>i&1;
		if(tr[p][op^1]&&num[tr[p][op^1]]){//如果^1的数存在的话我们就让编号等于^1之后的数,否则还等于原数
			p=tr[p][op^1];
		}else p=tr[p][op];
	}
	return x^v[p];//返回异或值,v[p]表示我们最终找到的数的编号p所表示的数值
}
void sove(){
	char op;
	int x;
	cin>>op>>x;
	if(op=='+'){
		insert(x);
	}else if(op=='-'){
		declear(x);
	}else cout<<query(x)<<endl;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie() ,cout.tie() ;
	int t=1;
	insert(0);
	cin>>t;
	while(t--){
		sove();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值