题解:这题是你自己出的¶
贡献:Codex(GPT-6)补齐加密规格,给出分块数对矩阵、二维树状数组和按值AVL位置树的组合算法,完成证明、实现与验证。
将区间分成整块和边角¶
设块长为 \(B\) ,块数 \(K=\lceil n/B\rceil\) .块 \(b\) 中值 \(v\) 的频数记为 \(c_b(v)\) .维护矩阵
它表示第 \(b\) 块与第 \(d\) 块之间的有序相等数对数;对角线也按有序对计数,包含同一位置。用二维树状数组维护 \(F\) 的单格增量和矩形和。
同时按值建立位置集合,使用带子树大小的AVL树支持某值在位置区间内出现多少次。节点以位置为键,修改时从旧值的树删除该节点,再插入新值的树。每块的值频数以及各值对应的树根使用有序映射。
查询分解¶
把第一个区间分为完整块部分 \(I_0\) 与边角 \(I_1\) ,第二个分为 \(J_0,J_1\) .每份边角至多含 \(2B\) 个位置。答案由三个互不重叠的集合组成:
- \(I_0\times J_0\) :一次矩阵矩形和。
- \(I_1\times(J_0\cup J_1)\) :逐个枚举第一区间边角位置,用该值的位置树统计整个第二区间。
- \(I_0\times J_1\) :逐个枚举第二区间边角位置,在第一区间完整块覆盖的连续位置范围内统计。
此分解适用于重叠区间。不要在第三项查询整个第一区间,否则边角之间的数对会重复计数。没有完整块时,整个区间都是边角;处理一次即可。
修改矩阵¶
把块 \(b\) 中一个值 \(x\) 改为 \(y\) .\(x=y\) 时直接结束。对于 \(d\ne b\) ,只有矩阵的第 \(b\) 行和列改变,两个格子的增量都为
对角格只更新一次,其增量为
这些频数取修改前的值。更新矩阵后再修改频数和位置树。
矩阵定义在初始化时成立,上述公式精确描述每次修改,因此一直成立。位置树由正确的插入、删除和子树大小维护保持准确。查询的三部分恰好划分所有有序数对,故输出正确。随后使用该答案解密下一行,归纳可知所有操作都按实际含义处理。
初始化、复杂度和实现¶
按值收集出现过的块及频数。某值出现于 \(d_v\) 个块,就枚举这 \(d_v^2\) 个块对建立矩阵。因为 \(d_v\le K\) 且 \(\sum_v d_v\le n\) ,工作量最多 \(O(nK)\) ,而不必枚举所有位置对。
预处理 \(O(n\log n+nK+K^2\log^2(K+1))\) .单次修改为 \(O(K(\log(B+1)+\log^2(K+1))+\log n)\) ;查询为 \(O(B\log n+\log^2(K+1))\) .空间 \(O(n+K^2)\) .实现取 \(B=400\) ;块长是时间折中参数,不影响正确性。
std.cpp 使用标准C++17,不依赖扩展顺序统计树。AVL树的旋转同时重算高度和子树大小。二维计数、答案和编码字段使用64位类型;负数解码显式按补码规则计算,避免依赖越界无符号到有符号转换。
逐查询扫描区间并统计频数是独立检查模型,但最坏 \(O(nm)\) .只预存块对矩阵而没有位置秩结构,会使边角统计过慢;离线莫队不能预先获得尚未解密的查询。这些候选不作为当前完整范围的补充解法。
性能¶
正式数据每份运行五次并另测峰值。标准程序最慢中位数 0.707113 秒,峰值 30.11 MiB;按2倍取整到0.5秒,时限为 1.5 秒。 环境说明与逐次测量可供复现;其他环境需重新校准。