可持久化数据结构
一些需要 历史信息 时,我们可以根据 时间 进行可持久化操作。
1. 可持久化线段树
3. 可持久化 Trie
和可持久化线段树一样的思想,没插入一个数,新建 \(\log{V}\) 个节点,剩下的节点向 已有节点 相连即可。
可持久化 Trie 后我们考虑每个节点 \(i\),建立一个大根堆,存 \(n\) 个节点除选过的,\(s_i\) 与其余点的最大值,每次选出堆顶,更新一下即可。
复杂度 \(\mathcal{O}(n\log{V} + k\log{n})\)。
II CF241B Friends
上一题的加强。
\(k\) 比较大,不考虑关于 \(k\) 的解法。
首先可以二分,二分 \(mid\),我们求出所有与 \(s_i\) 异或值 \(\geq mid\) 的个数,可持久化 Trie 可以解决,判断一下,可以找到第 \(k\) 大的异或值。具体在每个节点有一个 \(size\) 存其字节点个数,查询时找出 \(\geq mid\) 的点加上即可。
然后问题就转化成了找出与 \(s_i\) 异或值 \(\geq z\) 的值的和,我们在 Trie 上存储所有字节点的 \(01\) 个数,拆一下贡献,查询时加上即可。
但是由于 异或和等于 \(z\) 的方案可能不止一个,所以我们需要统计一下方案数,减去多余的贡献。
时间复杂度都是 \(\mathcal{O}(n\log^2{V})\),空间复杂度也是 \(\mathcal{O}(n\log^2{V})\) ,可能需要卡卡。
复杂度极其劣,跑的巨慢,其实可以直接不用可持久化,不过我没想到。
树剖比较 native,我们考虑分成两个 可持久化 Trie,一个维护 \(dfn\) 序,一个维护到根路径,这样求个 \(LCA\),查询一下,复杂度时 \(\mathcal{O}(n\log{V} + m\log{n})\)。