第一次写字典树题,记录一下
#include<cstdio>
#include<iostream>
#include<cmath>
#include<vector>
#include<map>
#include<algorithm>
#define xf_dycm ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long int
#define ll long long
using namespace std;
//const ll mod=1e9+7;
const int MAXN=5e6+10;
ll pi,li;
ll q;
//01字典树
//把每个数字都转成2进制,按32位来存
ll trie[MAXN][2];//存字典树,存的是当前节点标号,下面连接的数字可能有1和2
ll tot=1;
ll num[MAXN];
void ist(ll n){
ll P=0;//从树根开始
for(int i=31;i>=0;i--){
int ch=(n>>i)&1;//取二进制
if(trie[P][ch]==0){
trie[P][ch]=tot;
tot++;
}
P=trie[P][ch];//P代表当前节点标号
num[P]++;//标记这条分支上有几个士兵
}
}
void dlt(ll n){
ll P=0;
for(int i=31;i>=0;i--){
int ch=(n>>i)&1;
P=trie[P][ch];
if(!P)return;
num[P]--;//这条分支上的士兵要少一个
}
}
ll srh(ll p,ll l){
ll ans=0;
ll LL,PP;
ll P=0;
for(int i=31;i>=0;i--){
PP=(p>>i)&1;LL=(l>>i)&1;
if(LL==1&&PP==1){
ans+=num[trie[P][1]];
P=trie[P][0];
} //l:1 p:1 +num[0] ->1
else if(LL==1&&PP==0){
ans+=num[trie[P][0]];
P=trie[P][1];
} //l:1 p:0 +num[1] ->0
else if(LL==0&&PP==0){
P=trie[P][0];
}//l:0 p:0 ->1
else if(LL==0&&PP==1){
P=trie[P][1];
} //l:0 p:1 ->0
if(!P)break;
}
return ans;
}
signed main(){
xf_dycm;
cin>>q;//q次查询
ll op;
while(q--){
cin>>op;
if(op==1){
cin>>pi;
ist(pi);
}
else if(op==2){
cin>>pi;
dlt(pi);
}
else {
cin>>pi>>li;
cout<<srh(pi,li)<<endl;
}
}
}