支持增删元素、全局异或、前K小求和的序列操作算法优化问题
优化方案
核心优化思路
首先解决原有实现的两个最大性能瓶颈:
- 异或操作无需真的遍历修改所有元素,用全局异或懒惰标记实现O(1)更新:维护一个变量
global_xor,所有元素的实际值等于存储值异或global_xor,执行Xor(x)时直接global_xor ^= x即可。 - 放弃用vector存储全量元素,改用**01二进制字典树(01Trie)**维护元素的计数、位分布信息,支持O(log M)复杂度完成增删、前K小和查询,其中M是元素最大值(这里是1e5,最多17位二进制)。
01Trie节点设计
每个节点存储两类统计信息:
cnt:当前子树包含的元素总个数bit_cnt[17]:当前子树的所有元素中,每一位二进制位上1的出现次数(用于快速计算子树内所有元素异或global_xor后的总和)next[2]:指向0、1两个子节点的指针/索引
各操作实现逻辑
Add(x)
- 计算要插入Trie的原始存储值:
val = x ^ global_xor(保证后续取实际值时val ^ global_xor = x符合预期) - 从Trie根节点开始,从最高位(第16位)到最低位(第0位)遍历
val的每一位:- 若对应位的子节点不存在则创建
- 移动到对应子节点,将节点
cnt加1 - 若当前位是1,将节点
bit_cnt[当前位]加1
Remove(x)
- 计算要删除的原始存储值:
val = x ^ global_xor - 从Trie根节点开始,从最高位到最低位遍历
val的每一位:- 若对应位子节点不存在或节点
cnt为0,直接终止(元素不存在) - 移动到对应子节点,将节点
cnt减1 - 若当前位是1,将节点
bit_cnt[当前位]减1
- 若对应位子节点不存在或节点
Xor(x)
直接执行global_xor ^= x,时间复杂度O(1)。
Sum(K)
K超过当前总元素个数时直接返回所有元素的和,否则从根节点开始逐位计算前K小的和:
- 初始化结果
res = 0,当前节点为根节点 - 从最高位(第16位)到最低位(第0位)遍历:
- 取
global_xor当前位的值b - 优先走异或后为0的分支(对应子节点索引为
b ^ 0):- 若该分支存在且分支
cnt >= K:直接移动到该分支,继续下一位 - 否则:计算该分支所有元素异或
global_xor后的总和,加到res中;K减去该分支的cnt,移动到另一个分支(索引b ^ 1)
- 若该分支存在且分支
- 取
- 遍历完所有位后,剩余K个相同的最低位元素的和加到
res中,返回最终结果
其中分支总和计算逻辑:对每一位i,若(global_xor >> i) & 1为1,则该位贡献为(分支cnt - 分支bit_cnt[i]) * (1 << i),否则贡献为分支bit_cnt[i] * (1 << i),所有位贡献相加就是分支总和。
复杂度说明
所有操作的时间复杂度都是O(log 1e5) ≈ O(17),整体总复杂度为O(n * 17),完全可以支撑n=1e5的规模。
内容的提问来源于stack exchange,提问作者little.dinosaurs
相关产品推荐
相关产品推荐

