矩形加,矩形求和
很经典的扫描线问题。
考虑一个初始全为 \(0\) 的二维数组 \(a_{x,y}\),有 \(m\) 次修改操作,每次给定 \(l_1, r_1, l_2, r_2, v\),对所有 \(x \in [l_1,r_1] \land y \in [l_2, r_2]\) 的位置加上 \(v\)。修改结束后,再给出 \(q\) 次询问操作,每次给定 \(l_1, r_1, l_2, r_2\),求 \(x \in [l_1, r_1] \land y \in [l_2, r_2]\) 的位置的和。
\(m, q \le 10^6, 1 \le l_1, r_1,l_2, r_2 \le 10^6\)。
经常的变式是:询问给定 \(L \le l \le r \le R\),求一些 \([l,r]\) 某些权值和状物。这常常被认做区间历史版本和。这当然是可做的,一般来说用矩阵维护是最好写的,但是常数比较大;一些维护一堆 tag 的方法又特别需要注意转移顺序,对于这类平凡的模板题可能有点大炮打蚊子。
考虑一个类似树状数组区修区查的转化方法。扫描线扫到 \(i\) 的时候,我们期望对每个 \(j\) 维护出:\(d_{j}=\displaystyle\sum _{x=1}^i\sum _{y=1}^ja_{x, y}\),这样用差分就能直接算出答案。修改考虑到可以在 \(y\) 方向上维护差分数组。可以直观考虑差分对于 \(d_j\) 的贡献。容易发现贡献形如一个等差数列,一个简单的维护方法就是考虑把 \((r-l)c \to rc - lc\) 直接摊到右端点上去做就行了。复杂度 \(\mathcal O((m+q) \log n)\)(\(n\) 是离散化后的 \(l, r\) 最大值),常数大概为 \(4\)。而矩乘版本的区间历史版本和则是 \(27\),尽管优化后都还带有线段树的大常数。
另外一方面,这个问题可以用分块优化(?),当 \(m,q\) 明显不同阶时,用分块把问题变成 \(\mathcal O(1) - \mathcal O(\sqrt n)\)
或 \(\mathcal O(\sqrt n) - \mathcal O(1)\) 可以降低一定复杂度。

矩乘版本的区间历史版本和的简单优化就是用 vis 标记一下有用的转移,打表打出来就行了。

浙公网安备 33010602011771号