二阶前缀和和二阶差分

发布时间 2023-10-15 10:25:54作者: carp_oier

马上就要csps 了还啥也不会,真就是酸菜鱼了。

定义

二阶差分就是在差分数组的基础上再做一次差分。

举个很板的栗子就是对一个序列进行一个等差数列式的一个减法,这个时候我们可以通过二阶差分,在 \(O(1)\) 的复杂度进行修改,之后就是 \(O(n)\) 的二维前缀和,就可以维护出来我们的一个序列了(至于比较灵活的应用还不会,等我会了upd,或者就是等我退役了直接再等 \(\infty\) 年更新)

例题

T1

三步必杀

这个题目就是我上面说的等差数列维护就好了,很板的一道题。(

这个题目可以推出来,我们在维护二维差分数组的时候,我们进行的单点 修改应该是这样的:

\(c_1\) 为修改时候的等差数列的第一项,\(d\) 为等差数列的公差,\(c_m\) 为等差数列的 末项,\(l\) 为等差数列修改的左边界,\(r\) 为等差数列的右边界,\(d\)为我们的二维差分数组 。

我们修改的地方就应该为

\[d[l] \gets d[l] + c_1 \]

\[d[l+1] \gets d[l + 1] + d - c_1 \]

\[d[r+1] \gets d[r + 1] - d - c_m \]

\[d[r + 2] \gets d[r + 2] + e \]

T2

P1438

这个题目其实也是和上面的题目一样,但是我们需要考虑在修改的同时维护一个前缀和,不难想到用树状数组来进行维护(树状数组又好写,又常数小,谁不爱用呢 )。由于我们对原数组进行了差分,所以我们求一个位置的时候应该是求这个位置的二阶前缀和,然后我们在修改的时候是进行四次单点修改(修改位置同上)。下面我们就要推式子然后看我们树状数组是要维护什么:

\(d\) 为一阶差分序列,\(d'\) 为二阶差分序列。

\[\begin{aligned} a _ i &= \sum _ {j = 1} ^ i d _ i \\ &= \sum _ {j = 1} ^ i \sum _ {k = 1} ^ j d' _ k \\ &= \sum _ {j=1} ^ i (i - j + 1) d' _ j \\ &= (i + 1)\sum _ {j = 1} ^ i d' _ j - \sum _ {j = 1} ^ i j \times d' _ j\end{aligned} \]

这个时候我们就知道我们需要通过树状数组维护两个东西:一个是 \(d' _ i\)的前缀和,另一个是 \(j \times d' _ j\) 的一个前缀和。

啥时候才能不用学知识的菜鱼啊