2018.10.15【NOIP练习】hyc的xor/mex(01TRIE)

01Trie树解决MEX问题
本文介绍使用01Trie树处理带有XOR操作的MEX查询问题,通过动态维护全局XOR标签,实现高效查询最小未出现数。文章详细解释了01Trie树的插入和查询过程,特别注意动态开点情况下空节点的处理。

传送门


解析:

卡了我好久。。。明明是一个裸的 01 T R I E 01TRIE 01TRIE。。。

思路:

显然由于修改只有 x o r xor xor操作,所以我们可以方便的把所有数插入一个 01 T R I E 01TRIE 01TRIE,并且维护一个全局 x o r t a g xortag xortag,这样就可以随时知道任何数当前值。

对于询问 m e x mex mex,我们直接在 T R I E TRIE TRIE树上带着 x o r t a g xortag xortag跑,尽可能向 x o r xor xor后的0儿子跑,跑到满的节点就直接向另一个儿子走,这样能够保证总是跑到一个合法的,并且尽可能的小的点。

最后,如果是动态开点的 T R I E TRIE TRIE树,请注意走到空节点的情况,我就是这样被卡的。

不明白为什么其他人建了权值线段树,(反正没我的 01 T r i e 01Trie 01Trie快)


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline int getint(){
	re int num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

inline void outint(int a){
	static char ch[13];
	if(a==0)pc('0');
	while(a)ch[++ch[0]]=a-a/10*10,a/=10;
	while(ch[0])pc(ch[ch[0]--]^48);
}

cs int N=300005;
struct _01TRIE{
	int son[N*21][2];
	int siz[N*21];
	int tot;
	int xortag;
	void insert(int x){
		int now=0;
		for(int re i=20;~i;--i){
			bool f=x&(1<<i);
			if(!son[now][f])son[now][f]=++tot;
			now=son[now][f];
			++siz[now];
		}
	}
	
	int query(){
		int now=0,ans=0;
		for(int re i=20;~i;--i){
			bool f=xortag&(1<<i);
			if(!son[now][f])return ans;
			if(siz[son[now][f]]==(1<<i)){
				ans|=1<<i;
				now=son[now][!f]; 
			}
			else now=son[now][f];
		}
		return ans;
	}
}Trie;
bool vis[N];

int n,m;
signed main(){
	n=getint();
	m=getint();
	for(int re i=1;i<=n;++i){
		int x=getint();
		if(!vis[x])vis[x]=true,Trie.insert(x);
	}
	while(m--){
		int x=getint();
		Trie.xortag^=x;
		outint(Trie.query());pc('\n');
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值