一类巧妙利用利用分治的序列求值

I.PreFace

这个方法经常用于这类问题:

给定序列 (A),并定义基于序列 (A) 的函数 (f(l, r)),求 (sumlimits_{1 leq i leq j leq n}f(l, r))

这个方法的核心做用是:

将不满足可减性的求值,变成只需要可以区间拼合(即满足区间可加性)的求值式子。

II.常用的解决办法:

  1. 拆成每个点的贡献处理。

  2. 从左到右推进端点 (r),开一个数据结构维护对于当前每个 (l) 的函数值 (f(l,r)),每推进一位 (r) 对应了一次的区间修改和一次的整体求和。

etc,这不是本文的重点。

III. 正文

考虑分治:

这回我们只要求跨过中点的区间的贡献就够了,即求

[sum_{i=l}^{mid}sum_{j=mid+1}^{r}f(i,j) ]

这个式子当然还是是 (O(n^2)) 的,但是常常它比原问题的那个更加的简便,有无穷的威力。简便在哪?简便在于,本来这个式子可能不满足区间可减性,但是经过这样的分治,它只需要区间可加就行了,于是可以转化为第 II 节中的方法。

设当前求解当前 (mid) 的时间复杂度为 (O(f(r-l+1))),那么总复杂度也就近似的可以认为是 (O(f(n) log n)

IV. 随便的一道例题:

给定数列 (A),设 (f(l,r)=maxlimits_{i=l}^{r}A_i),求 (sumlimits_{i=1}^nsumlimits_{j=i}^n f(i,j))

利用上述转化后问题就变成了可以用第 II 部分中的第一种处理,设 (g(i)) 为前缀/后缀最大值,那么它一定是单调的,即对于每一个位置的最大值的贡献,我就看一下另一边有多少个数小于它即可。尺取法一下复杂度 (nlog n)。事实上还有很多其他解法,这里只是作为一个 example。

V. 练习题:

GSOR 1008,谢谢出题人 lxl。

哈哈哈其实他给的做法都是 (n log^2 n) 的,其实很轻松可以做到 (nlog n),于是就成了最短+最快解(哈哈哈!

as 0.4123
原文地址:https://www.cnblogs.com/Linshey/p/14165532.html