-
\(\text{P4551}\) 最长异或路径
- 算法:\(\text{trie}\)
题目:
给你一棵带边权的树,求 \((u,v)\) 使得 \(u\) 到 \(v\) 的路径上的边权异或和最大,输出这个最大值。
点数不超过 \(10^5\),边权在 \([0,2^{31})\) 内。
题解:
设 \(f(u,v)\) 为 \(u\) 到 \(v\) 的路径上的边权异或和的值。
那么对于求出每一组 \((u,v)\) 求出 \(f(u,v)\) 效率低下。
考虑对于树的一个指定根 \(rt\),可以通过 \(rt\) 来得到 \(f(u,v)\)。
具体地说,就是考虑 \(f(u,v)=f(u,rt) \oplus f(rt,v)\),由于 \(lca(u,v)\) 以上至根的部分重复,所以重复部分异或值为 \(0\),那么此式子成立。
所以对于一点 \(u\),考虑算出所以的 \(f(rt,u)\)。
但是这样复杂度仍为 \(O(n^2)\)。瓶颈在于每次都要计算 \(dis(u,rt)\)。
所以考虑将 \(f(u,rt)\) 插入一棵 trie 中,所以就可以更快地求出 \(f(u,rt)\)。
考虑用一个贪心:对于每个数转为其二进制数,从高位比较,进行异或,若异或值大显然值也大,所以顺此路线往下走。