看到集合和异或,可以想到01tire(但是我没有想到)。
让后就可以对于每次插入和删除一个数,都在01tire树上操作即可。让后记录一下到当前位(当然是从高位到低位啦)有相同前缀的数的个数。例如样例建图出来大概是这样的:
可以看到从编号为2的点开始有分歧,这个时候当前p的位为1,l的位为0,显然我们需要走右边才可能能使其答案小于l,否则答案直接大于l了。让后到6的位置,这个时候当前p的位为1,l的位为1,显然我们可以右儿子加上值为1的数的数量,让后往左走,因为左边虽然当前前缀于p异或之后和l相等,但是可能也有小于l的数。也就是我们每次都要往与l当前位在p与当前值异或之后相等的位置走,这样就可以解决问题啦。不过要注意如果当前位l为0的时候,p与当前值异或之后一定要为0。
注:这个地方为了方便根的编号要设置为1,不能设置为0,相应的idx初始值也要为1。因为在solve函数里,搜索查询的数的时候,我们不能保证每个访问到的结点都已经申请了空间,当然也可以每个都申请,但是麻烦还废空间。所以当访问的空间不存在的时候,son [ p ] [ u ] 值为0,如果你设置的根编号为0,那么这个时候不就正好是根了嘛?所以这里根不能设置为0。
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=6000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int q;
int son[N][2],cnt[N],idx=1;void insert(int x)
{int p=1;for(int i=30;i>=0;i--){cnt[p]++;int u=x>>i&1;if(!son[p][u]) son[p][u]=++idx;p=son[p][u];}cnt[p]++;
}void delet(int x)
{int p=1;for(int i=30;i>=0;i--){cnt[p]--;int u=x>>i&1;if(!son[p][u]) son[p][u]=++idx;p=son[p][u];}cnt[p]--;
}int solve(int x,int t)
{int p=1,ans=0;for(int i=30;i>=0;i--){int u=x>>i&1;int s=t>>i&1;if(u<s) ans+=cnt[son[p][0]];if(u&&s) ans+=cnt[son[p][1]];if(!s) p=son[p][u];else p=son[p][u^1];}return ans;
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);scanf("%d",&q);while(q--){int op,p,l; scanf("%d%d",&op,&p);if(op==1) insert(p);else if(op==2) delet(p);else{scanf("%d",&l);printf("%d\n",solve(p,l));}}return 0;
}
/**/