*题解:P7502 「HMOI R1」不知道是啥的垃圾题
解析
记 \(c_i\) 表示 \(c\) 的二进制第 \(i\) 位(从低往高,从\(0\) 开始编号)。那么对于一组 \((x,y),(a,b)\),考虑 \(x \operatorname{xor} a\) 与 \(y \operatorname{xor} b\) 的最高不同二进制位 \(i\),显然对于更高位 \(j>i\),我们有 \(x_j\operatorname{xor} a_j=y_j \operatorname{xor} b_j\),即 \(x_j \operatorname{xor} y_j=a_j\operatorname{xor} b_j\)。
这下就好做了,开一个 Trie 存储 \(a\operatorname{xor} b\) 并维护子树内当前层对应位 \(a_i=1\) 的个数。对于询问 \((x,y)\),让 \(x\operatorname{xor} y\) 在 Trie 上走,每走一层就计算令当前位为最高不同二进制位时,满足条件的 \((a,b)\) 个数,即另一侧子树的 \(a_i = x_i \operatorname{xor} 1\) 的个数。
时间复杂度 \(O(M \log x)\)。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e5 + 5,M = 60,K = 10000 + 5,mod = (int)1e9 + 7;
int son[N * M][2],cnt1[N * M],cnt2[N * M],siz = 1;
void insert(int p,int i,ll x,ll y){
int b = bool((x ^ y) & (1ll << i));
if(!son[p][b]) son[p][b] = ++siz;
cnt1[son[p][b]]++;
cnt2[son[p][b]] += bool(x & (1ll << i));
if(!i) return;
insert(son[p][b],i - 1,x,y);
}
void del(int p,int i,ll x,ll y){
int b = bool((x ^ y) & (1ll << i));
cnt1[son[p][b]]--;
cnt2[son[p][b]] -= bool(x & (1ll << i));
if(!i) return;
del(son[p][b],i - 1,x,y);
}
int ask(int p,int i,ll x,ll y){
int b = bool((x ^ y) & (1ll << i));
int res = 0;
if(x & (1ll << i)){
res += cnt1[son[p][b ^ 1]] - cnt2[son[p][b ^ 1]];
}else{
res += cnt2[son[p][b ^ 1]];
}
if(!son[p][b]) return res;
return res + ask(son[p][b],i - 1,x,y);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out1.txt","w",stdout);
int m;
cin>>m;
while(m--){
ll op,x,y;
cin>>op>>x>>y;
if(op == 1){
insert(1,M,x,y);
}else if(op == 2){
del(1,M,x,y);
}else{
cout<<ask(1,M,x,y)<<'\n';
}
}
return 0;
}

浙公网安备 33010602011771号