考虑单独处理的时候是怎么样的。先扔掉期望,这实际上是 i 号点站了 (in) 个人,然后问所有人到某一个点的距离之和。单独处理的一种做法是从最左端开始移动 x,记录当前答案和左右两边各站了多少人。一开始左边没人,右边站了 2n。跨越 i 号点,就要将左右两边站的人数和答案做一次系数为 (in) 的更新。预处理组合数可以简单解决。
现在的问题是要把所有询问整合处理。我们在移动的时候只关照了 x 维度,对于 n 维度目前似乎是没有办法。考虑 n 变到 n+1 的过程,实际上是每一个点的人有丝分裂成人数相同的两拨人分别往左右移了一个。对于远离 x 的点,两拨人左右各移动一格抵消贡献了,实际上贡献恰好翻倍了。如果 x 作为上一轮的点,设当前有 (in) 个人,则贡献为翻倍和 2(in),因为有两拨 (in) 的人从这个点离开走了一步 (in);左边和右边的人都同时翻倍且加上了 (in)。如果 x 作为下一轮的点,设左边有 (jn) 个人,右边有 (j+1n),则贡献仅有翻倍,左边和右边的人都同时翻倍且各减去 (jn) 和 (j+1n)。这不难理解。对于 n 变到 n−1 同理。也就是,我们实际上可以通过维护左边、右边的人数和当前答案去做到变化 n 的复杂度是线性的。
那么更改 x 和 n 移动 1 的复杂度是 Θ(1) 的。发现这不就是莫队吗。然后莫队直接上。时间复杂度 Θ(NN)(N=2×105)。注意这篇题解为了方便理解把期望扔掉了,实际写代码的时候需要加上期望系数。