普通Trie
UVA11732 “strcmp()” Anyone?
把每个单词插入到一颗 trie 里面,然后对 trie 的每个节点统计一下经过该节点的单词个数,就可以统计出所有到当前节点的这一位相等,但之后的部分不相等的所有字符串的两两比较次数,最后统计答案时扫描整颗 trie 即可。
1 |
|
01Trie
所谓 01Trie,其实就是把每个数当成了一个01串,可以处理很多异或方面的问题还可以当平衡树用
它和权值线段树相比的优势在于常数更小,空间占用也更小。
HDU4285 Xor Sum
模板题,把每棵树当作一个01串插入到 trie 中,查询的时候考虑一个贪心:
我们优先选择最高位和查询数字不同的,再考虑次高位,在考虑第三高位……按照这个贪心原则搞就好了,我写的是递归,其实改成迭代常数小得多。
1 |
|
可持久化Trie
Trie的可持久化,和主席树是一个道理,都是重复利用之前的节点,但代码非常精简。
盗图方便理解:
P6088 [JSOI2015]字符串树
对于每个点都建立一颗 trie,里面存储着所有从根节点到这个节点路径上的字符串,查询的时候在 $u,v$ 中查询答案,再减去 lca 答案的二倍。
1 |
|
可持久化01Trie
如果看懂了上面三种 trie 可持久化 01trie 其实是个很自然的东西,不用我多解释了。
BZOJ3689 异或之
和 NOI2010 的那道超级钢琴一样,把每个 $i$ 对应的最小的 $a_i\oplus a_j$ 放到一个堆里面,然后每次堆 pop 一个 $i$ 后,又插入第二小的 $a_i\oplus a_j$……以此类推,重点在于如何求出 $i$ 固定,$i<j$ 时,第 $k$ 小的 $a_i\oplus a_j$。
第 $k$ 小这个条件可以直接 trie 上二分,具体过程为对每个 trie 节点记录经过该节点的数个数,如果 $k$ 小于这个个数,那么递归进入异或值较小的那一棵子树,否则进入较大的那颗子树。
区间第 $k$ 小,我们做区间第 $k$ 小数的时候把线段树换成了主席树,这里就把 01trie 换成了可持久化 01trie。
ps:想一想其实这个题用不着可持久化,直接用全局的 trie 就可以了,但可持久化 01trie 甚至比普通 trie 还好写,比 01trie 也多不了几行代码,所以我就强行把它当作可持久化 01trie 的例题了(((
1 |
|