已补(1/9)
A
B
C
D
E
F
G
2100 H
题意
三个操作,加入一个数
,删除一个数
,询问有多少个数满足
。
给出的是
。
题解
首先因为是不等号,不能进行正常能进行的异或运算。
首先前两个操作暗示了
树,具体操作是什么呢?
逐位判断,比如说
的第
位是
,那么此时查询的时候,就顺着
往下走,此时不能确定当前的数是多是少。
但是如果是
,当前如果有
,那么肯定往
走,如果有
,能保证
往下的都会小与
,直接统计。
因为添加删除的时候都是直接在链上操作,所以没有问题,除了初始节点,每一条边的指向都对应一个点。
即解。
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define sf(x) scanf("%d",&x)
using namespace std;
typedef long long ll;
const int maxn = 100000*30+500;
const ll mod = 1e9+7;
int val[maxn];
int ch[maxn][2];
struct Trie{
int sz;
void init(){
sz=1;
memset(ch,0,sizeof(ch));
memset(val,0,sizeof(val));
}
void insert(int x){
int u=0;
for(int i=30;i>=0;i--){
int c=(x>>i)&1;
if(!ch[u][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
val[u]++;
}
}
void del(int x){
int u=0;
for(int i=30;i>=0;i--){
int c=(x>>i)&1;
if(!ch[u][c])return ;
u=ch[u][c];
--val[u];
}
}
int query(int x,int y){
int u=0,ret=0;
for(int i=30;i>=0;i--){
int c=(x>>i)&1,now=(y>>i)&1;
if(now==0){
if(ch[u][c])u=ch[u][c];
else return ret;
}
else{
if(ch[u][c])ret+=val[ch[u][c]];
if(ch[u][c^1])u=ch[u][c^1];
else return ret;
}
}
return ret;
}
}trie;
int main(){
trie.init();
int n;cin>>n;
for(int i=1;i<=n;i++){
int op,p,l;sf(op);
if(op==1){
sf(p);
trie.insert(p);
}
else if(op==2){
sf(p);
trie.del(p);
}
else{
sf(p);sf(l);
int ans=trie.query(p,l);
printf("%d\n",ans);
}
}
}