首先把题目转换一下,可以得到以下题面:
有一个长度为 $n$ 的序列 $a$,求两两异或的前 $K$ 大值。
本质和 CF241B Friends 一样。
$Tricks:$
补全三角形矩阵,答案 $\div 2$。
考虑建立可持久化 $Trie$。之后考虑两种情况。
如果 $K$ 和 $n$ 是同阶的,我们可以得到一个 $K \log K$ 的算法。
我们维护一个大根堆,常规维护一下第 $K$ 小。之后考虑每一个位置的贡献。我们不妨考虑每一个位置作为右边位置的贡献。那么就是求左边异或第 $K$ 小。
对于每一个位置都这样做。可以保证有答案。
当取出一个元素的时候,更新答案,然后使用当前元素计算比其小 $1$ 个 $rank$ 的答案,放入堆。
可以得到复杂度是 $O((n + k) \log (nk))$。
$n$ 是插入的复杂度, $k$ 是堆的复杂度。
如果 $n$ 比较小,然后 $k$ 是 $n^2$ 级别的呢?
我们考虑对于所有的数都插入到 $Trie$ 里面。
发现如果可以得到第 $K$ 大的值,那么计算比其小的值可以通过 $O(n \log^2 w)$ 的复杂度计算得到。
然后我们直接暴力二分加 $check$ 得到第 $K$ 大就好了。
所以这种问题的复杂度可以做到 $O(n \log n + \min(k \log k, n \log ^ 2 w))$。
如果您想练练类似的题目的话,推荐一下。
代码确实简单,就不放了。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Legendgod's Blog!
评论