Trie树
学习内容
01字典树(01-trie)是一种特殊的字典树,它的字符集只有{0,1},主要用来解决一些关于二进制上的问题,例如异或问题和子集问题等。
例题分析
给定n个数,求ai和aj之间的最大异或值
状态变化
将数组中所有正整数的二进制表示,按照从高位到低位的顺序,当作字符串挂载在trie树上,然后贪心的走,每一次走跟当前位相反的一位就可以了。时间复杂度为O(logn)
代码复现
maxn = 210000
ch = [[0]*2 for _ in range(maxn)]
val = [0] * maxn
n, ans, tot = 0, 0, 0
def insert(x):
global tot
now = 0
for j in range(31, -1, -1):
pos = ((x >> j & 1))#从最高位开始构建树
if ch[now][pos] == 0:#表示这个点还没有用上
tot += 1#这里表示第几个点
ch[now][pos] = tot
now = ch[now][pos]#将目前记录到的第几个点写下来
val[now] = x #记录第now个节点对应的值
def query(x):
now = 0
for j in range(31,-1,-1):
pos = ((x >> j) & 1)
if ch[now][pos ^ 1] != 0:#如果找到对应的异或值
now = ch[now][pos^1]#把结果记录
else:
now = ch[now][pos]
return val[now]#获得对应序号的值
n = input()
for i in range(1, n+1):
x = int(input())
insert(x)
for i in range(1, n+1):
ans = max(ans,query(val[i]))
print(ans)
例题分析1
给定一棵树和树上的边权,求两点之间路径异或值的最大值。n<=1e5
状态分析
dfs 处理出根节点到所有节点的边权异或值,随后把它们扔进01Trie中。为了让异或值最大,我们可以枚举节点,在Trie上贪心:从高到低位,尽量选和当前数二进制位不一样的,随后再与原节点异或值异或一下,取 max。
感悟
异或运算当中,一个数同时异或两次可以消掉,所以在查询树上两点间的路径权重和的时候,可以先求每个点到树根的异或值,然后再将点之间的值异或。
蓝桥杯云课学习笔记分享,欢迎大佬们批评指正!
一直在进步就好咯!
by 闻不多