首先将限制转化为 ≤R 。
建出反串的后缀树,执行静态链分治(即树上启发式合并)。
设当前结点包含字符串的最长长度为 len,则考虑子树内的后缀 i,j 的贡献。
显然是 min(R−(ai⊕aj),len)。
考虑分类讨论。
若 ai⊕aj≤R−len,需要这部分的数对的个数。
若 R−len<ai⊕aj≤R,需要这部分的数对的 ai⊕aj 之和以及个数。
则问题变为维护一个多重集 S,支持对于 i∈S,查询满足 i⊕v≤R 的 i 的个数以及 i⊕v 的和。
可以考虑使用 Trie 来维护,查询时在 Trie 上走 v⊕R 的路径,当某个时刻 R 的当前位为 1,则意味着若走向另一个儿子,异或值的这一位会变为 0,故将答案加上另一个儿子子树内的贡献即可。
当然,还要加上 v⊕R 本身的贡献。
而同时要查询和,可以套路地维护每一位 1 的个数来支持查询。
时间复杂度 O(nlognlog2ai)。
因为这是一棵后缀树,可以相信良心出题人没有卡树剖,所以是可以过的。
当然,在 SA 的 height 数组上并查集启发式合并或所谓「启发式分裂」并使用可持久化 Trie 也是可以的。
实际上这两种做法都相当于在 height 数组的笛卡尔树上做静态链分治,而 height 数组的笛卡尔树和后缀树某种意义上是等价的。
代码:
1 |
|