证明1: 修改(时间)t的可逆变化
时间T的swap,而 swap 带来的可逆性和时间轴的自由移动,才是让这个算法在逻辑上成立且代码极其优雅的“灵魂”。
[2 ... 6]
完全正确!一语道破天机。
你的这句话非常精准地总结了带修莫队的运行机理:“物理修改是全局的,答案统计是局部的”。
我们可以把这两点对应到代码上,会看得非常清楚:
cpp
inline void update(int change_idx, int L, int R) {
int pos = changes[change_idx].pos;
// --- 局部贡献 (View) ---
// 只有当修改发生在你当前盯着的窗口 [L, R] 里时
// 颜色的变化才会影响当前的统计结果 ans
if (pos >= L && pos <= R) {
del(pos); // 旧颜色贡献消失
}
// --- 全局修改 (Model) ---
// 无论你在不在看这个位置,世界的真实状态(数组)必须改变
// 这样是为了保证当你以后移动 L, R 经过这里时,看到的是正确的值
swap(a[pos], changes[change_idx].val);
// --- 局部贡献 (View) ---
// 同上,只有在窗口里,新颜色才会计入统计
if (pos >= L && pos <= R) {
add(pos); // 新颜色贡献产生
}
}
为什么必须是全局修改?
哪怕修改的位置 pos 远在十万八千里之外(不在 [L, R] 内),我们也必须执行 swap。
因为莫队的
恭喜你,理解到这一层,带修莫队对你来说已经没有秘密了!它本质上就是一个在三维空间中,一边游走一边维护局部统计量的算法。
把change[k]想象成,通过一个地铁安检门,每次你经过这道门,保安都会把你身上的东西留下来,然后再把他的东西给你, 那么你经过这道门两次(你可以想象成你上班的时候,经过一次,下班的时候又经过一次),你的原来的东西就还原了