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

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





