Friends
题目链接:luogu CF241B
题目大意
给你一个序列,然后要你把序列里数两两异或得到的值从小到大排序,要你求前 k 大的值的和。
思路
首先考虑找到第 k k k 大是多大,因为异或嘛,自然想到 Trie 树。
于是就在 Trie 数上每个数放上去找位置,然后全部一起走可以做到 n log n n\log n nlogn,如果外面单独二分则是 n log 2 n n\log^2n nlog2n 都可以。
这里补一句因为题目要的是 i < j i<j i<j,这样不太好搞,不过 i = j i=j i=j 的时候是 0 0 0,所以我们可以试着取消这个限制,发现就只会重复一倍的共贡献(当然你选的数量也要翻倍)
然后考虑怎么统计,也是考虑每一位逐个统计,为了方便我们把数组排序,这样连续的一段数在 Trie 数上最后投射的位置也是连续,于是可以每个子树一个 l , r l,r l,r 表示里面的有的点的区间。
然后就类似于在树上再走,然后把大于的部分都统计了。
统计大于的部分就弄 f i , j , k f_{i,j,k} fi,j,k 为第 i i i 位,前 k k k 个数中有多少个数这一位是