*题解: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;
}
posted @ 2026-08-28 14:57  yutar  阅读(7)  评论(0)    收藏  举报