一道傻逼题

题目描述

给定\(n\)个非负整数数\(a_1\)\(a_2\) , \(a_3\) \(\cdots\) \(a_n\),对于所有 \(1<=i<j<=n\),求出\(a_i \; xor \; a_j\)

求在得到的\(n*(n-1)/2\)个数
中的前\(k\)大的和。

对于\(30%\)的数据,\(n<=500\)

对于另外\(30%\)的数据,\(0<=ai<=1023\)

对于\(100%\)的数据

\(n<=5*10^5,k<=2*10^5,k<=n*(n-1)/2 ,\; 0<=ai<=10^9\)

时间限制:\(2s\) 空间限制:\(512M\)


\(30pts\)

直接求出任意两个数的xor值 , 然后丢到数组里排序。

\(60pts\)

讲真的我也不知道这档部分分怎么拿

难道真是给那些\(01Tire\)高度只开\(10\)的人???

\(100pts\)

我是个菜逼,所以我用的是可持久化\(01Tire\) , 求第\(k\)\(O(nlog^2n)\)
,统计答案\(O(nlog^2n)\) , 空间复杂度是\(O(nlogn)\)

通过这种比较劣的方法过了这个题

如果你做过异或粽子那这个题还是蛮好想的(

求异或前\(k\)大,显然可以通过\(O(nlog^2n)\)的可持久化\(01Tire\)上二分来求出第k大

但是题目让我们求得是前\(k\)大异或后和

我们首先考虑一个问题怎么求\(01Tire\)上一个子树中所有值异或当前值之后的和

考虑一个数组排序后插入可持久化\(01Tire\) , 那么在\(01Tire\)中一个子树必定对应原序列的一个连续子序列

这样我们只要维护每个子树上最小值和子树中数的个数即可

之后处理一颗子树的时候就能在原序列上直接二分找答案然后\(O(logn)\)求出一个子树的贡献

一棵\(01Tire\)最多有\(logn\)个贡献 , 那么\(n\)棵的话就最多有\(nlogn\)个贡献,所以最终统计答案的复杂度是\(O(nlog^2n)\)

总复杂度\(O(nlog^2n)\) (自带巨大常数

所以你\(k\)开到\(10^9\)我也是可以做的

代码就不贴了 , 毕竟是考试题

禁止评论!!!


\(End\)

其实我异或粽子复杂度是\(O(nlog^3n)\),所以只有\(60pts\),有点遗憾 , 但这个题其实是比异或粽子更难那么一点的 , 对我来说还是有必要做一做吧

posted @ 2021-09-28 21:58  ·Iris  阅读(129)  评论(0编辑  收藏  举报