CF817E Choosing The Commander

在补NOIonline
先随手做一下这个T2的弱化版。
感觉这个就是T2的trick
(tire)树认知不够,数位思想差啊。

考虑用(tire)树维护数集,然后高位往低位处理(l),如果(l_i)(1),则和(p_i)相同一侧子树可以全部加入答案,再走和(p_i)不同一侧递归下去,若(l_i)为0,则必须走(p_i)同侧。

CF817E Choosing The Commander
#include<iostream>
#include<cstdio>
#define ll long long
#define N 100005

ll n;
int cnt;
int ch[N * 16][2],s[N * 16];

inline void insert(ll c){
	ll u = 0;
	for(int i = 30;i >= 0;--i){
		if(!ch[u][(c >> i) & 1])
		ch[u][(c >> i) & 1] = ++ cnt;
		s[u] ++ ;
		u = ch[u][(c >> i) & 1];
//		std::cout<<u<<" ";
	}
	s[u] ++ ;
//	puts("");
}

inline void del(ll c){
	ll u = 0;
	for(int i = 30;i >= 0;--i){
		s[u] -- ;
		u = ch[u][(c >> i) & 1];
	}
	s[u] -- ;
}

ll pi,li,ans;

inline void solve(ll u,ll dep){
	if(dep == 0)
	return;
	if((li >> (dep - 1)) & 1){
		ll x = (pi >> (dep - 1) & 1);
//		std::cout<<u<<" "<<1<<" "<<dep - 1<<" "<<x<<" "<<s[ch[u][x]]<<std::endl;
		if(ch[u][x])
		ans += s[ch[u][x]];
		if(ch[u][!x])
		solve(ch[u][!x],dep - 1);
	}
	else{		
		ll x = (pi >> (dep - 1) & 1);
//		std::cout<<u<<" "<<0<<" "<<dep - 1<<" "<<x<<std::endl;		
		if(ch[u][x])
		solve(ch[u][x],dep - 1);
	}	
}

int main(){
	scanf("%lld",&n);
	while(n -- ){
		ll opt;
		scanf("%lld",&opt);
		if(opt == 1){
			ll p;
			scanf("%lld",&p);
			insert(p);
		}
		if(opt == 2){
			ll p;
			scanf("%lld",&p);
			del(p);
		}
		if(opt == 3){
			scanf("%lld%lld",&pi,&li);
			ans = 0;
			solve(0,31);
			std::cout<<ans<<std::endl;
		}
	} 
}

ps:最近代码能力提上了,不过还要注意对拍。
以及我还是没搞懂(tire)要开多大空间,从这题上看,得开到(16n)(n字符串数量)啊。
下回弄懂了,回来补坑。

原文地址:https://www.cnblogs.com/dixiao/p/14897248.html