01trie树学习笔记

问题引入

给一个长为 n n n的数列,要求一个 a i a_i ai, a j a_j aj,使得 a i x o r a j a_i xor a_j aixoraj最大。

什么是01trie树

类似于字典树的做法,将每一个数化为二进制数,看作01串,插入到字典树中。

问题解答

首先建好01trie树,然后对于每一个数,在树上跑一遍贪心,即贪心选择与这个数当前位不同的那个节点。

也就是说,尽可能地保证越高的位的异或和为1,(因为高位的一个1比后面的位全为1都要大)

比如对于7,在下面这个插入了0,2,7的树上跑。
开始在0号节点,然后看最高位,7的最高位是1,所以为了保证当前位异或和为1,应走0的方向,也就是走到1节点。
然后看次高位,7的次高位为1,同理,走0的方向到3号节点,依次类推,得出与7异或的最大值为7。
在这里插入图片描述
然后遍历整个数组,对每一个数都这么跑一遍,就得出了异或最大值7.
复杂度 O ( n l o g n ) O(nlogn) O(nlogn).

两个扩展例题

1.第 k k k大异或和

题意:还是给出长为 n n n的序列,这次不求最大值了,求第 k k k大的 a i x o r a j a_i xor a_j aixoraj
做法:考虑二分答案,对于每个二分到的值 x x x,遍历数组跑一遍01trie树,看有多少组异或和是大于 x x x的,然后根据大于 x x x的异或和的组数向上向下二分。
如何计算大于 x x x的组数?
遍历数组,对于每一个数 a i a_i ai,跑一遍01trie,记录比 x x x大的异或和的组数 a n s ans ans。对于 x x x的每一位,若为1,则走树上与 a i a_i ai当前位相反的儿子,若为0,则走树上与 a i a_i ai当前位相同的儿子,并将与 a i a_i ai当前位相反的那个儿子的子树大小加到 a n s ans ans中。
由于每一组大于 x x x的二元组都会被计算两次,所以最终的 a n s ans ans还要除以二。
复杂度 O ( n l o g n l o g n ) O(nlognlogn) O(nlognlogn).

2.树上最大异或路径

题意:给定一棵 n n n个点的带权树,寻找树中找两个结点,求最长的异或路径。
异或路径指的是指两个结点之间唯一路径上的所有边权的异或。
做法:观察得到,从 i i i~ j j j的路径的异或值为 i i i到根的异或和 x o r xor xor j j j到根的异或和。
因此将例题中的 a i a_i ai转化成节点 i i i到根的异或和的值,就可以照着例题的方法做了。
复杂度 O ( n l o g n ) O(nlogn) O(nlogn).

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值