一道傻逼题
题目描述
给定\(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\),有点遗憾 , 但这个题其实是比异或粽子更难那么一点的 , 对我来说还是有必要做一做吧