CF837G Functions On The Segments

洛谷 CF

  • \(n\) 个分段函数,第 \(i\) 个函数形如:

\[f_i(x)=\begin{cases}y1_i,\space \space \space \space \space \space \space \space\space \space \space \space x\le x1_i\\a_ix+b_i,\space \space \space \space x1_i<x\le x2_i\\ y2_i,\space \space \space \space \space \space \space \space\space \space \space \space x>x2_i\end{cases} \]

  • \(m\) 次询问,每次询问给出 \(l,r,x\),求 \(\sum\limits_{i=l}^r f_i(x)\)

  • \(n\le 7.5\times 10^4\)\(m\le 5\times 10^5\)强制在线

首先,所有函数都可以表达成一次分段函数形式(注意这里强调的是形式上相同)。

\(f_i(x)=p_ix+q_i\),其中:

  • \(x\le x1_i\) 时,\(p_i=0,q_i=y1_i\)

  • \(x1_i<x\le x2_i\) 时,\(p_i=a_i,q_i=b_i\)

  • \(x>x2_i\) 时,\(p_i=0,q_i=y2_i\)

考虑对于一次查询,求的就是:

\[\sum_{i=l}^r f_i(x)= \sum_{i=l}^r (p_ix+q_i)=\left(\sum _{i=l}^rp_i\right)\cdot x+\sum_{i=l}^r q_i \]

\(x\) 给定,只需要维护 \(p_i\) 以及 \(q_i\) 的区间和即可。

最大的麻烦是 \(p_i\)\(q_i\) 在动态变化。不过我们考虑将所有分段函数分段的起点全部存到一个数组 \(P\) 里面。并将其从小到大排序,设其大小为 \(k\)

则对于同一条分段函数 \(f_i(x)\) 来说,当自变量 \(x\) 取值为 \(x_1,x_2\),满足存在一个 \(j\,(1\le j< k)\) 使得 \(x_1,x_2\in[P_j,P_{j+1})\) 时,\(\boldsymbol{f_i(x_1)=f_i(x_2)}\)

就是说将这些点投影到数轴上时,这些点将数轴分成若干段,若自变量 \(x\) 取在相同的一段里时,则函数值相同。

很好理解,因为同一段内不存在一个分段函数的起点,对于任意函数来说不存在一个函数发生变化的地方。

因此我们对于数轴上的每一段,维护这一段对应的 \(p_i,q_i\) 的区间和。由于强制在线,考虑使用可持久化线段树维护每一段的信息。

将所有变化表示成差分的形式并离线扫描线。当开启一个新段的时候,在上一段版本的基础上扫描并进行这一段的修改。由于每一段可能产生多次修改,因此主席树上的版本仍然记“第几次修改之后”,再维护一个新数组记录每一段的最终版本(即最后一次修改的版本)。

查询时,先二分找到 \(x\) 在哪一段,然后在对应的版本上查询即可。

时间复杂度为 \(\mathcal{O}((n+m)\log n)\),空间复杂度为 \(\mathcal{O}(n\log n)\)

提交记录(含代码)

posted @ 2023-10-25 15:10  lzyqwq  阅读(20)  评论(0)    收藏  举报