链上二次求和
作者:互联网
正在肝的一道黑题……
首先处理那个奇怪的询问操作。我们可以对于那个奇怪的东西进行暴力推式:
\[ans(l,r)=\sum\limits_{len=l}^r\sum\limits_{i=1}^{m-len+1}\sum\limits_{j=i}^{i+len-1}{a_j} \]用前缀和搞一下就是
\[\sum\limits_{len=l}^r\sum\limits_{i=1}^{m-len+1}{sum_{i+len-1}-sum_{i-1}} \]分离一下
\[\sum\limits_{len=l}^r{(\sum\limits_{i=len}^m{sum_i}-\sum\limits_{i=0}^{m-len}sum_i)} \]emmmm,发现它似乎仍然具有前缀和的性质,考虑搞个前缀和的前缀和(\(su\)):
\[\sum\limits_{len=l}^r{su_{m}-su_{len-1}-su_{m-len}} \]展开:
\[su_m\times(r-l+1)-\sum\limits_{i=l-1}^{r-1}su_i-\sum\limits_{i=m-r}^{m-l}{su_i} \]于是那个奇怪的询问就变成了单纯的对于su数组的区间和查询。
按照思考此类问题的惯常方法,考虑假如我们给\([l,r]\)中的数都加了一个\(a\),会发生些什么?
\[\Delta sum_i=\begin{cases}0&i\in[1,l-1]\\d\times(i-l+1)&i\in[l,r]\\d\times(r-l+1)&i\in[r+1,m]\end{cases} \]同样可以得出,假如\(s(i)=i\times(i+1)/2\):
\[\Delta su_i=\begin{cases}0&i\in[1,l-1]\\d\times s(i-l+1)&i\in[l,r]\\d\times s(r-l+1)&i\in[r+1,m]\end{cases} \]发现对于\(i\in[r+1,m]\),每个点位的变化值是相同的,可以用一个线段树来维护,这就是普普通通的线段树基本操作。接下来重点来看一下\(i\in[l,r]\)部分。
\[\frac{2\Delta su_i}{d}=(i-l+1)^2+(i-l+1)\\=i^2+(l-1)^2+2i(1-l)+i+(1-l)\\=i^2+(3-2l)i+(l-1)(l-2) \]发现\((l-1)(l-2)\)是固定的,相当于是区间加。于是我们就需要一种数据结构可以完成区间加下标平方和区间加下标。这应该是可以做到的。于是主要的问题变成了pushnow函数的书写。区间加下标好办,那区间加下标平方曾么搞?有平方和公式啊。
\[\sum\limits_{i=1}^{m}{i^2}=\frac{m(m+1)(2m+1)}{6} \]所以pushnow函数就可以写了。只是不知道如此这般地用三个线段树是不是会超时啊。
标签:limits,二次,求和,sum,len,times,链上,su,cases 来源: https://www.cnblogs.com/dai-se-can-tian/p/15830289.html