2021 年 7 月 7 日提高组模拟赛题解

A : 最大子段和

题目描述

给定一个长度为 \(n\) 的数列 \(a\) ,从这个序列中选出不相交的两个连续段,要求它们的和最大,请你求出这个最大的和。具体的,你需要给出 \(A,B,C,D\) ,满足 \(1 \leq A\leq B < C \leq D\) ,并且最大化下面的式子:

\[\sum_{i=A}^B a_i +\sum_{i=C}^D a_i \]

\(1 \leq n \leq 10^5 ,1 \leq |a_i| \leq 10^5\)

Solution

考虑枚举分界点 \(k\) ,使得所选的区间 \([A,B]\)\(k\) 的左边(可以包含 \(k\) ,即 \(B \leq k\)),所选的区间 \([C,D]\)\(k\) 的右边(不能包含 \(k\) ,即 \(C>k\)),因为分成的这两部分完全独立,所以可以分别求出这两部分的最大子段和,即可求出以 \(k\) 分界的最大子段和。

\(k\gets1,2 \dots n-1\) ,求出所有 \(k\) 的最大值即可。

至于求最大子段和,可以用 DP 分别预处理前缀最大子段和和后缀最大子段和。

时间复杂度 \(\mathcal{O}(n)\)

B : 序列

给定一个长度为 \(n\) 的序列 \(a\) ,初始值全部为 \(0\)\(m\) 次操作,每次操作有 \(4\) 个参数 \(l,r,s,e\) ,表示将区间 \([l,r]\) 加上一个首项为 \(s\) ,末项为 \(e\) 的等差数列。

求出操作完成之后数列的每一项,为了避免输出过多,你只需要输出数列的异或和。

\(1 \leq n ,m \leq 5 \times 10^5,2s\),保证任何时候输入和数列的数在 long long 范围内。

Solution

把原序列差分,设差分之后的数组为 \(b\) ,在区间 \(l,r\) 加上一个首项为 \(s\) ,末项为 \(e\) ,公差为 \(d\) 的等差数列,可以发现: \(b_l\gets b_l+s,b_{r+1}\gets b_{r+1}-e\) ,同时对于 \(l+1\leq i \leq r - 1\)\(b_i \gets b_i+d\)

于是把差分数组再次差分,即可 \(\mathcal{O}(1)\) 实现区间加。举个例子,设再次差分的数组为 \(f\) ,在区间 \(l,r\) 加上一个首项为 \(s\) ,末项为 \(e\) ,公差为 \(d\) 的等差数列,\(f\) 的变化为:

\[f_l\gets f_l+s \\ f_{l+1}\gets f_{l+1}-s+d \\ f_{r+1}\gets f_{r+1}-e \\ f_{r+2}\gets f_{r+2}+e \\ f_r\gets f_r-d \]

最后对再次差分的 \(f\) 数组做两次前缀和,即可得到原数组。

时间复杂度 \(\mathcal{O}(n)\)

C : 柠檬

给定 \(n\) 个集合,第 \(i\) 个集合初始只包含元素 \(i\),开始时所有元素的权值为 \(0\) ,有 \(m\) 次操作:

  • 合并元素 \(x\) 所在的集合和元素 \(y\) 所在的集合。
  • \(x\) 所在集合的所有元素的权值加上 \(k\)

操作完后输出所有元素的权值。

\(1 \leq n ,m\leq 5 \times 10^5,1 \leq k \leq 100\)

Solution1

考虑线段树合并。用并查集维护每一个元素所对应的树根是哪个。对于合并操作,直接合并两个元素所对应的线段树。

对于整个集合加上一个数的操作,直接对于整个子树打上一个标记即可。记得在合并和查询的时候下方标记。

时间复杂度 \(\mathcal{O}(n \log n)\)

Solution2

把每个集合看成是一棵树,那么所有集合构成了森林。

对于合并操作,建立一个虚点 \(p\) ,令 \(x\) 所在子树的根节点和 \(y\) 所在子树的根节点的父亲都指向 \(p\)

对于整个集合加上一个数的操作,直接在这个子树的根节点打上一个标记即可。

最后从每一棵数的根节点开始 DFS ,自顶向下累加标记,当访问到元素 \(x\) 时,累加的标记就是 \(x\) 的值。

时间复杂度 \(\mathcal{O}(n)\)

posted @ 2021-07-08 21:54  recollector  阅读(143)  评论(0编辑  收藏  举报