trie树(一)01trie

本文介绍01 Trie树在解决区间异或问题中的应用,包括寻找最大异或值、处理树形结构上的路径异或最大值等问题。通过具体实例讲解了如何构建01 Trie树并实现贪心策略。

trie树是个好东西,而它有一类专门的应用,是用来处理区间异或的问题的,考虑到异或操作中我们只关心0/1,因此01tire也就是一种每一个节点最多只有两个儿子的树,具体操作其实跟普通trie树差不多,具体看例题吧

Xor Sum

大意:
给定一个序列,m次询问,每次询问一个值s,求区间中与s异或后结果最大的元素

思路:

对于给定的s,我们考虑它的二进制表示,现在就是要尽可能使得它的每一个非1位都有一个0对应。很明显这个条件不是能肯定满足的,所以我们可以贪心地来处理这件事情。

我们发现,对于一个数的二进制表示,最高位对结果的贡献是大于之前所有位的贡献之和的,所以,如果我们从高到低遍历每一位时,只要当前这一位能满足异或后得到1,我们就一定取这个值。

但是可能有很多的数都满足当前这一位的最优解,而它们的低位不同,自然会影响结果。所以我们考虑以序列中的每一数的01序列建trie树。这样我们的决策就不再是选哪个树了,而是往树的哪一条路往下走。按照贪心的策略,这显然是很好实现的。最后我们只要在每一个序列的末尾标记一下它对应的数字是哪一个,最后输出就好啦

ps:trie树的空间,要开够,这里一般就是数字数*最长01序列长度(=32),而且2^32爆int了,记得开ll

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const ll N=5e5+10;
ll tr[N*32][3];
ll idx=0;
ll mas[N];
ll as[N*32];
ll n,a,b,c,m;
void insert(ll x)
{
	ll p=0;
	for(int i=31;i>=0;--i)
	{
		bool id=(x>>i)&1;
		if(!tr[p][id]) tr[p][id]=++idx;
		p=tr[p][id];
	}
	as[p]=x;
}
ll find(ll x)
{
	ll p=0;
	for(int i=31;i>=0;--i)
	{
		bool id=((x>>i)&1);
		if(tr[p][!id]) p=tr[p][!id];
		else p=tr[p][id];
	}
	return as[p];
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;++i) cin>>mas[i];
	for(int
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值