#5523. 云斗学院 2025 年国赛前公益训练营训练赛 #3 题解
云斗学院 2025 年国赛前公益训练营训练赛 #3 题解
当前没有测试数据。
A
LOJ3685 难度 2
考虑寻找合法解的性质,发现如果有解,那么一定存在一种方案使得每个人开始走之后,直接不停顿地走到终点。
证明:考虑合法解中某个人 的相邻两次行动 ,由于走的是最短路径,必有 。
我们考虑如果这两次行动在总的行动序列上不相邻,它们中间有若干次行动,由于此时 位于点 ,因此其他人的任意行动都不能经过 。以 为根建树,那么中间的行动可以划分为三部分:
- 完全在 子树内的部分
- 完全在 子树内的部分
- 其他的部分
借用官方题解的图:
于是我们可以重排操作序列为:
- 先进行完全在 子树内的部分。
- 然后让 这个人从 。
- 然后进行 子树内的部分和其他部分。
这样一直操作下去,一定可以构造出一种解满足每个人开始走之后,直接不停顿地走到终点。
于是我们考虑两个人 如果满足 或者 ,那么 就得在 前面走。这样会连出来一张有向图,如果是 DAG 就有解,否则无解。
直接连会得到 条边,许多数据结构都能将其边数优化至 。优化之后就可以过了。
B
LOJ3692 难度 2
对于修改,如果修改了和 距离不超过 的一个点 ,我们发现在 处计算贡献似乎不可避免地要带上 log。设 ,我们考虑在 的 级祖先 的位置计算贡献。
那么要求 或者 。可以发现,这样的确能不重不漏地统计完所有贡献。具体来说,对每个点 我们记录 表示 子树内和他距离为 的所有点进行的修改。修改时我们枚举 的祖先 ,将 和 计入这次贡献。查询时枚举 的祖先 ,把 累计进答案。
有一个细节是 可能不存在 级祖先,我们在根节点往上再加 个点即可。
总复杂度 。
C
QOJ7088 难度 3
考虑一个串 ,考虑找到所有的 使得 。
枚举 ,设 ,那么我们只需要找到 中所有长度 的连续段。
注意到连续段的段数不超过 ,考虑一段一段找。发现长度 就至少需要经过 这些位置中的一个,考虑枚举 ,算出经过 的极长连续段长度。那么只需要查询 的最长公共后缀与 的最长公共前缀即可。SA 配合 ST 表容易做到 。
现在我们找到了一个极长的连续段 ,那么相当于要对每个 ,连边 ,边权为 。我们按照 从小到大考虑,那么只需要能找到那些真的发生合并的位置就好了,因为虽然边数超过了平方级别,但是合并次数至多是 。
具体地,我们考虑建一个 ST 表,这个 ST 表的含义是:如果 ,说明我们可以确定 分别和 有连边;如果不等,那么我们不确定他们是不是真的连好了(也就是说,可能这两个数不相等,但是他们代表的区间的确有对应连边)
现在考虑如果我们要对 和 连边,首先拆成两个长度为 的区间连边,那么要找到这个区间中所有的实际有效(造成连通块合并)的连边,就只需要从 和 往下递归,做一个类似在线段树上递归的过程;然后我们在第 层把 和 对应的极大连通块合并,可以启发式合并或者直接并查集维护。
这样每一层都只会有最多 次合并,总的合并次数就是 ;如果在并查集中实现路径压缩+按秩合并,复杂度就是 。注意虽然有 次区间连边,但总共的有效合并次数还是 级别,所以复杂度只有 1 个 。
D
Luogu10365 难度 3
定义区间 能到 当且仅当只往 开始倒水,最后 会被覆盖。
只需要求能到达每个区间的区间个数。设 为能到 的区间个数,则答案为 。
对每个区间 ,找到 上面的第一个区间和 上面的第一个区间,设这两个区间分别为 ,我们建两棵树,第一棵树上 的父亲为 ,第二棵树上 的父亲为 。
那么我们会从 一路向上扩展,直到被完全覆盖。找到这个完全覆盖的,那么合法区间就是覆盖过程中经过的若干段阴影区域拼起来。这些阴影部分可以被差分为 往上跳的若干个矩形减去 往上跳的若干个矩形内的线段个数。于是只需要倍增求一下链上和就好了。
这里还需要求第一个被覆盖到的区间,发现这就是支配树上它的父亲,只需要求 DAG 的支配树。这个很好求:任取拓扑序,对每个 ,其入边分别为 ,找到 ,则 的支配点就是这个 LCA。连边接着递推即可。
E
ARC105F 难度 3
设 分别表示从点集 内选边,得到一个连通/任意二分图的方案数,其集合幂级数为 。自然地,有 。
考虑怎么算 ,发现有一个自然的想法是,钦定每个点的颜色,然后异色边任选,同色边一定不能选。但这样会有问题,对于一个有 个连通块的二分图,我们会将其计算 次。
记这样算出来的值是 ,其集合幂级数为 。那么实际上,我们发现有 ,因为每多一个连通块,方案数就会再乘 。由于 ,得到 。于是 。
可以用一遍子集卷积算出,综上所述,总复杂度 。
F
QOJ8049 难度 3
考虑给每个合法序列 pair 对应唯一的一个加数的顺序,每次如果当前 就加一个 ,否则加一个 。那么每种方案对应唯一的顺序,且每个顺序中, 的值永远在 之间。
于是 表示加入了 ,目前 的方案数即可。
每次如果 就转移到 ,否则转移到 。转移用前缀和优化,复杂度 。
G
LOJ3688 难度 3
显然任意时刻 肯定是最终串的一个区间,因此我们考虑区间 DP。
设 表示合成 所需的最小代价,分最后一次有效操作是粘贴还是加字符讨论。
如果是加字符,有 。
如果是粘贴,那么如果粘贴了一个 ,考虑到剪切的时候会直接变成空串,于是我们一定是先用最小代价构造出 ,然后需要算出,如果剪贴板里面是 ,那么构造出 最少需要多少代价。
如果粘贴一次还不如直接加字符,即 ,那显然没有用。
否则我们应该粘贴尽可能多次,也就是说要在 中找到尽可能多的不交子串 。
考虑先枚举 ,然后枚举 ,对所有的 做贡献。枚举完 之后,设 ()为 中子串 的最多不交出现次数,我们相当于要做转移
$$f(k+1,r)+B+(r-l+1-c_l\times (r-k))\times A+c_l\times C\to f(l,r) $$注意到 ,考虑对一段相同的 一起做贡献,那么是一个区间对公差为 的等差数列 chkmin 的形式,可以简单维护。这样对一个 ,只需要 次区间 chkmin。进一步发现区间可以放宽成前缀,于是可以 进行一次操作。
现在还需要求一个 前面 最后一次出现的位置,注意我们会对一个 询问若干递减的 ,在 SAM 上定位到 这个节点,然后在 endpos 集合里维护一个指针即可做到均摊 。当然也许用 hashmap 也可以做到 。
综上,总复杂度 。
H
LOJ3490 难度 4
首先,我们有 的算法,即每次跑一遍 dijkstra,同时记录到每个点的最短路以及这个最短路对应的时刻。可以证明只要这样就能得到最优解。
把路径分成两类:在一天内完成的,和至少有一次等待到下一天的。
对于在一天内完成的路径,我们考虑找到其中限制最严(也就是经过这条边的时间最接近他的限制时间)的一条边 ,假设我们是从 走到 ,起始时间为 ,如果走到点 的时候时刻为 ,那么我们知道这条边的 是所有边里面最小的一个。
我们把起始时刻加上 ,可以发现路径仍然合法。于是有如下的算法:枚举每条边 ,计算 表示想要从 走到 ,满足:
- 整个过程必须在一天内完成。
- 到达 时,当前时刻 。
这种情况下所需的最小时间。这可以通过一遍 dijkstra 在 的时间内算出,同时也可以算出 表示如果要求能走这个最短路, 的起始时间最晚是多少。再通过一遍 dijkstra 算出 表示从 到 ,起始时间为 ,所需的最少时间(这个过程同样必须在一天内完成)。
算出这些之后,我们就可以计算 这条边对所有点对 的贡献,即对于起始时间 ,都有一种 的方案。
现在考虑跨越多天的路径,注意到如果在某个城市 进行等待,一定是等待到第二天的 时刻,然后在 时刻出现在某条边 的终点 。
于是类似地,我们枚举路径上第一条进行等待的边 ,同理算出 (只不过此时从 开始走的时候,我们允许它跨越多天完成),更新答案即可。
最后再对每个点对 ,我们把贡献到 上面的若干条路径按照 排序,然后预处理后缀 min,即可在 的时间内回答一组询问。这里可能要对 个长度为 的数组排序,但注意到对于一个 ,所有 的分段点总共只有 个,于是只需要进行 次排序。
综上,总复杂度 。
I
Luogu10356 难度 4
考虑两个单调的序列,长度分别是 ,他们合并起来的最小的 怎么算。
发现合并之后会得到一个长度为 的序列,同时会分成 段,而且显然新插入的数要么可以放到左边的段内,要么可以放到右边的段内,于是下界是 。
我们发现下界一定是可以取到的。钦定 的划分,以及划分点分到左边还是右边,直接顺次填入,如果出现了 这样导致两个段合并的,发现总可以把 向前提一位或者向后放一位从而分隔开。那么这样交换会不会相交呢,发现需要这一段长度为 ,而且两边都向另一侧钦定,发现这个时候一定不如直接向 的这一侧钦定。于是答案就是 。
接下来考虑一般情况,把 分段,如果答案想要为 ,那么需要两边分的段数都够用。设左边的段长构成序列 ,右边是 ,考虑 ,即 ,可以算出
$$a_i+y\le xy+x\iff a_i-x\le (x-1)y\\\iff y\ge \left\lceil\frac{a_i-x}{x-1}\right\rceil=\left\lfloor\frac{a_i-2}{x-1}\right\rfloor $$于是只需要 。另一边也一样。
注意到两边只有一个会卡满约束。考虑对一个 算有多少区间符合条件,用总数减掉两边分别卡掉的即可。考虑怎么算卡掉的,发现相当于取若干整段和两个散段。
枚举左端点 所在整段,对于 同段的形式,此时算出的 $\lfloor (r-l+1)/(x-1)\rfloor\le \lfloor n/(x-1)\rfloor$, 枚举结果容易算出方案数,进而计算贡献;对于 不同段的,我们可以从分段点处分开,那么贡献为 处的散段贡献与 左边的若干整段和一个散段贡献之和,也就是要算
其中 表示 到这一段右端点的贡献, 表示 左边的若干整段和一个散段的贡献之和, 表示 中选一个长度 的区间的方案数,这个是一个前面二次函数后面平着的形式。
这个形式不完全是二次函数,直接维护一次项和二次项可能会算错后面的部分(也是我场上 FST 的原因)。
注意到 不超过这一段的段长除以 ,我们考虑枚举 的值,算出 ,这样复杂度也就是调和级数。双指针维护最大的 满足第一个 的 在这一段内,然后可以算出具体的分段点在哪里。
那么对 前面段内的 我们需要维护 ,后面段内的 直接维护个数即可,这一段的一个前缀的 有一个等差数列求和以及等差数列平方和的形式,可以 算出。
综上,总复杂度 。
- 这个实现起来非常的麻烦,建议你先写一个最简单的暴力,然后一点一点地优化。
J
QOJ8543 难度 4
考虑如果确定了每个字符串的长度以及 ,那么实际上字符串的形态是确定的:如果 ,那么一定是保留一段前缀;否则一定是不断循环,直到长度为 。
考虑一个 ,发现不管怎样一定是加一段前缀,或者删一段后缀,这样得到的所有 都是由 的若干个前缀拼接得到。考虑如果拼的前缀长度分别为 ,那么如果某两个 的 序列相同,显然 ;否则我们令 ,那么只要两个 的 不同,就一定有 。
考虑怎么样的 序列可以被生成出来,一开始 ,每次可以加上若干个 ,或者删掉末尾的若干个元素,然后把最后一个元素减小。我们考虑想生成一个目标 序列的话,发现只要 ,我们就可以直接加一个 到末尾去;否则我们一定得不到 。所以 序列合法当且仅当 。
于是要算 ,就只需要计数满足 的序列 个数。
枚举 ,相当于计数 的序列个数;枚举个数 ,容斥钦定 个 ,可以得到总的方案数是
$$\begin{aligned}&\sum_{k=1}^n\sum_{m=0}^{n-k}\sum_{j=0}^{\lfloor n/k\rfloor}(-1)^j\binom{m}{j}\binom{n-jk-k}{m}\\ =&\sum_{k=1}^n\sum_{j=0}^{\lfloor n/k\rfloor}(-1)^j\binom{n-jk-k}{j}\sum_m\binom{n-jk-j-k}{m-j}\\ =&\sum_{k=1}^n\sum_{j=0}^{\lfloor n/k\rfloor }(-1)^j\binom{n-jk-k}{j}2^{n-jk-j-k} \end{aligned} $$此时可以得到 的解法:对每个 暴力计算即可。通过对这个式子强行找递推式可以得到更优的做法,但更简单~~(并不简单)~~的方法是使用 GF:考虑答案的 GF
$$\begin{aligned} \sum_{i=0}^{\infty} x^iF(i)&=\frac{1}{1-x}\sum_{k=1}^{\infty}x^k\sum_{m=0}^{\infty}\left(\frac{x-x^{k+1}}{1-x}\right)\\ &=\frac{1}{1-x}\sum_{k=1}^{\infty}x^k\left(\frac{1}{1-\frac{x-x^{k+1}}{1-x}}\right)\\ &=\frac{1}{1-x}\sum_{k=1}^{\infty}\frac{x^k-x^{k+1}}{1-2x+x^{k+1}}\\ &=\sum_{k=1}^{\infty}\frac{x^k}{1-2x+x^{k+1}} \end{aligned} $$根号分治,取 。考虑 的时候,暴力展开 ,可以得到一个 的递推式:,于是可以 计算出他对所有 的贡献,这部分复杂度 。
对于 ,我们重新写一下上面的式子:
$$\begin{aligned} \sum_{k=B}^{\infty}\frac{x^k}{1-2x+x^{k+1}}&=\sum_{k=B}^{\infty}\frac{x^k}{(1-2x)\left(1+\frac{x^{k+1}}{1-2x}\right)}\\ &=\sum_{k=B}^{\infty}\frac{x^k}{(1-2x)}\left(\sum_{j=0}^{\infty}(-1)^j\frac{x^{(k+1)j}}{(1-2x)^j}\right)\\ &=\sum_{k=B}^{\infty}\sum_{j=0}^{\infty}\frac{(-1)^jx^{j+k(j+1)}}{(1-2x)^{j+1}}\\ &=\sum_{j=0}^{\infty}\frac{(-1)^jx^j}{(1-2x)^{j+1}}\sum_{k=B}^{\infty}x^{k(j+1)}\\ &=\sum_{j=0}^{\infty}\frac{(-1)^jx^j}{(1-2x)^{j+1}}\cdot\frac{x^{B(j+1)}}{1-x^{j+1}} \end{aligned} $$这里第二个等号利用了 。
注意我们只需要计算 的 的贡献,于是这样的 只有 个。考虑我们设
那么 。我们一开始令 ,然后每次 即可。
算一项 是 的,但做一次除法都是 的,于是这部分复杂度 ,总复杂度 。
K
Luogu11949 难度 5
下文不区分 。
- Subtask 3 的做法
最后相当于选取 中各一个区间,最大化它们的 乘上 之和。不难发现,我们选取的区间一定满足往左右扩展会导致 min 减小,或者干脆就无法扩展也就是顶到边界。那么 中选取的区间肯定是笛卡尔树上的区间; 中选取的区间则要么是完整的笛卡尔树区间,要么是某个原序列笛卡尔树区间和询问区间 的交。
在 subtask 3 中,询问区间总是笛卡尔树区间,于是只需要考虑选取一个完整笛卡尔树区间的情况。我们可以先 提前对 个笛卡尔树区间预处理答案,然后做一个二维数点。总复杂度 。
- 做法
根据上面的分析,我们发现可以在 时间内解决选取完整笛卡尔树区间的 case,现在就剩下选取不完整区间的情况。这意味着一定是选询问区间的一段前缀或者一段后缀。我们不妨就假设选取的是一段后缀。
设 表示序列 中满足所有数都 的区间的最长长度,我们考虑扫描线扫 ,维护序列 ,其中 表示以当前 为右端点的区间中, 的区间的最长长度;那么如果没有 那边的限制,答案就是 的全局最大值;进一步我们发现 那边的限制其实可以这样处理:我们钦定的 这一侧的最小值必须得严格大于整个询问区间 的最小值,对于选取整个区间的情况单独考虑。这样可以发现区间就不会超出 了。
现在考虑如何维护 ,发现 的时候相当于把 做区间 ,以及 覆盖为 ;以及还需要查询一个后缀中 的最大值,其中 是提前预处理的定值。这个问题可以使用分块配合凸包维护,做到 。实测是能过的。
- 做法
我们考虑假如询问区间是 ,选取了笛卡尔树区间 ,笛卡尔树区间中的最小值为 ,那么此时实际的区间是 。不妨考虑 的情况,其贡献为
其中 表示序列 中最长的一个区间,满足区间中的数全部 。
这是一个关于 的函数,我们可以提前按照 递增扫描线,维护一个可持久化李超树就可以支持 单次查询出一个 的值。现在我们要查询所有满足 的 ,他们的 的最大值。
注意到一个性质:任意两个 ,他们的 两个函数至多只有一个交点。因此我们可以使用李超树来维护 的单点处最大值;对于 的限制,扫描线扫 ,每次遇到一个 的时候做一个李超树区间插入,查询只需要在 个节点上求一次值。
最后把另一种情况反过来再做一遍,复杂度就是 。