[BJOI2018] 链上二次求和 题解

题目链接

原问题没法直接维护。先推式子,看看能得到什么。

f(l,r) 表示给定 l,r 时的答案。那么根据定义,有:

f(l,r)=len=lri=1nlen+1j=ii+len1aj

s(m)=i=1mai,则我们可以去掉第三个求和符号:

f(l,r)=len=lri=1nlen+1[s(i+len1)s(i1)]

ss(m)=i=1ms(i),继续推导,去掉第二个求和符号:

f(l,r)=len=lr[ss(n)ss(len1)+ss(nlen)]

sss(m)=i=1mss(i),继续推导,去掉最后的求和符号:

(为了应对边界条件,定义当 m0 时,ss(m)=sss(m)=0,这是自然的。)

f(l,r)=(rl+1)ss(n)+sss(r1)sss(l2)+sss(nl)sss(nr1)

以上,我们就去掉了所有的求和符号,这是进一步优化算法的基础。实际上,有了这个式子之后,我们就可以做到 O(1) 查询。但修改时,我们必须重新求出 s,ss,sss 数组,这样做的时间复杂度为 O(n)

想想怎么优化。看到题目中的区间操作,很自然地想到用线段树维护。那么,维护什么以及如何维护呢?

首先明确我们的需求:区间修改,快速计算 ss(m),sss(m)。从这里以后有两条路:

  1. 预处理出原序列 ass 数组。修改时,考察 a 的区间加对 ss 产生的影响,用线段树维护 ss 的区间和。维护 ss 的好处在于:sssss 的前缀和,因此要求 sss 时,只要在线段树上查询 ss 的区间和即可。

  2. 维护 a 和一些辅助数组,把 sssss 都写成用 a 表示的形式。

    注意 sssss 是不能作为区间信息维护的。实际上,带“前缀”的信息都不能作为区间信息维护。以更简单的一阶前缀和 s 为例,考虑这样的问题:区间加,求任意位置的前缀和。在线段树中,对于一个区间 [l,r],我们不能维护区间 [l,r] 的前缀和 s,因为这不能合并:[l,mid] 的前缀和与 [mid+1,r] 的前缀和相加,不能得到 [l,r] 的前缀和。我们只能维护 [l,r] 的区间和,而这个信息是可以合并的。求某个位置 p 的前缀和,看作 [1,p] 的区间和即可。

    如果选择这种方式,要继续推式子。

下面选用第二种方法。继续推导:

ss(m)=i=1ms(i)=i=1mj=1iaj=i=1m(mi+1)ai=(m+1)s(m)i=1miai

这里出现了新的求和式:i=1miai,我们记为 si(m),则

ss(m)=(m+1)s(m)si(m)

这样我们就把 ssssi 表示了出来。显然,s(m) 是容易用 a 表示的:对 a 求区间和即可。而 si 也是可以维护的——它不是某种“前缀”和的形式,因此可以在线段树上合并信息。至于如何维护,等会再说。

下面推导 sss 的式子:

sss(m)=i=1mss(i)=i=1m[(i+1)s(i)si(i)]=ss(m)+i=1mis(i)i=1msi(i)

i=1mis(i)i=1msi(i) 都不能直接维护,继续推导:

i=1mis(i)=i=1m(ij=1iaj)=i=1m(aij=imj)=i=1m12(m+i)(mi+1)ai=12i=1m(m2m+i2+i)ai=12m(m1)s(m)+12si(m)+12i=1mi2ai

(推到第二个等号的要点在于计算每个 ai 前的系数:这里,每个 aii 开始计算,系数为 i,然后为 i+1i+2,一直到 m,因此总系数为 j=imj。)

sii(m)=i=1mi2ai,和 si 类似,这也是可以合并的信息,因此可以用线段树维护。那么

i=1mis(i)=12m(m1)s(m)+12si(m)+12sii(m)

接着来推导 sss 的式子中剩下的另一个和式:i=1msi(i)

i=1msi(i)=i=1mj=1ijaj=i=1m(mi+1)iai=(m+1)si(m)sii(m)

(这里推导的要点在于把 iai 看作一个整体,然后推导方式和 ss 相同,只是把求和对象从 ai 换成了 iai。)

至此,我们终于可以写出 sss 的式子:

sss(m)=12m(m+1)s(m)+ss(m)(m+12)si(m)+12sii(m)

sssss 的式子可以看出,我们需要维护的量有 s,sisii。最后要考虑的是怎么维护区间加对这些量的影响。

考虑一个区间 [l,r],设它的三个量为 s,sisii(定义同上文)。设区间加 d 后,新的量为 s,sisii。那么

s=i=lr(ai+d)=s+di=lr1si=i=lri(ai+d)=si+di=lrisii=i=lri2(ai+d)=sii+di=lri2

对于 i=lr1,i=lrii=lri2,可以用公式求,也可以预处理后查表。这显然是好维护的。

回顾一下我们要做什么:

  1. 在线段树上维护 s,sisii
  2. 对于每次询问,根据公式求出答案。公式中要用到 sssss,这些也要代入公式求,但总归能化到我们维护的三个量。

每次询问时,我们只会在线段树上查询常数次,所以总时间复杂度为 O(n+mlogn)

综上所述,我们就解决了这个问题。

AC 记录

posted @   DengStar  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示