山东寒假集训2026 I
是的,你没有看错,我又来山东集训了。
Day 1
这几天讲课的居然是 yaoxi 哎。
yaoxi:大家觉得什么才是基础算法呢?
我们考虑整体二分。每次,我们把 \([l, r]\) 取中点 \(mid\),然后我们二分到 \([l, mid - 1]\) 和 \([mid + 1, r]\)。
接下来我们更改一下判定方法,我们把所有 \(x < k\) 的都设置为 \(1\),剩下的 \(k \le x\) 的设置为 \(0\),接下来我们使用双层树状数组来进行维护前缀和,剩下的每次在操作函数后面撤销即可。
上来就是紫题
- P2619 [国家集训队] Tree I。
我们考虑 wqs 二分。
wqs 二分,用一句话概括,就是这个玩意儿是个单调的,我们每次在 \([l, r]\) 中进行二分,二分到 \(mid\) 作为斜率,然后找这个类似函数的玩意儿的切点。接下来考虑如何判断切点。
我们把横坐标设置为 \(k\),纵坐标设为 \(ans\)。很明显,当且仅当 \(ans - mid \times k\) 最小的时候 \(k\) 就是切点。这里 \(ans\) 表示答案,\(k\) 表示白色点的个数。我们这才发现,这里和把所有的白色点的权值减掉 \(mid\) 是一致的。
所以,我们算法的流程就是,先二分斜率,然后进行最小生成树的计算,同时记录下此时的 \(k\) 的值,就可以了。
yaoxi 自信一交,先CE,后WA,然后WA,还是WA,依旧WA,仍然WA,终于,yaoxi:先下课,要是我没调出来就下一题。
-
P4383 [八省联考 2018] 林克卡特树。
貌似不难。
容易发现,答案具有单调性。我们不妨考虑 wqs 二分。我们直接就二分斜率,然后我们发现这不就是个树形 dp 吗,所以这就出来了。 -
P3199 [HNOI2009] 最小圈。
简单,二分,然后判个负环就行。 -
P3509 [POI 2010] ZAB-Frog。
简单简单。我们容易发现,对于一个 \(i\) 一一定可以维护一个长度为 \(k\) 的区间 \([l, r]\),所以这样我们就可以找到每个 \(i\) 所对应的 \(j\)。然后就是典的倍增了。
yaoxi:像这种矩阵快速幂只能做一次的错误思想我们一定要摒弃。
我们可以发现,设 \(f_i\) 表示答案,我们考虑 \(f_i = (f_{i - 1} \times 10^{\lg i + 1} + i) \mod k\)。
然后我们做 \(18\) 次矩阵快速幂即可。
-
P4159 [SCOI2009] 迷路。
我们容易发现 \(w_i \le 9\),我们不妨轻松地把一个点拆成 \(w_i\) 个,然后做 \(T\) 次矩阵快速幂即可。 -
P2151 [SDOI2009] HH 去散步。
典。见山东暑假集训 I的第一题。这还是伟大的 xby 老师讲的。 -
P4093 [HEOI2016/TJOI2016] 序列。
ds 好题。一道比较经典的 dp + cdq 好题。
我们考虑 \(f_i\) 表示前 \(i\) 中的答案,然后我们可以转移:\(f_i = \max f_j\),从中,满足条件:\(j < i\) 且 \(mx_j \le a_i\) 且 \(a_j \le mn_i\)。我们可以发现,这个其实是一个三维偏序,就可以使用动态 cdq 即可。 -
P4113 [HEOI2012] 采花。
我们发现每个数不容易统计次数,那么我们不妨考虑,\(pre_i\) 表示前一个的位置。那么我们就是求 \(\sum_{i = L}^{R} [pre_i < L]\),也就等价于 \(\sum_{i = 1}^{R} [pre_i < L]\)。我们把所有单次的操作综合起来,使用树状数组进行优化,复杂度是 \(O(n \log n)\)。 -
P4097 【模板】李超线段树 / [HEOI2013] Segment。
一种神奇的思路。我们考虑线段树,其中 \([l, r]\) 表示其中某一条线段包含了 \([l, r]\) 的所有点,且在 \(mid\) 处答案最优的。我们比如说插入一条线段,根据他们的斜率的大小关系,来判断哪一条向左边继续插入或者哪一个向右边继续插入。之后直接查询即可,复杂度 \(O(n \log n)\)。
yaoxi 锐评:我写的什么东西
- P3834 【模板】可持久化线段树 2。
经典。我们简单介绍一些。
主席树并不是传统意义上的线段树,而是一个类似于线段树的集合,每一个东西里面都会存在一个 \(rt_i\) 表示第 \(i\) 个线段树的根。然后,我们发现这个 \(rt_i\) 和 \(rt_{i - 1}\) 之间的关系。形式化的,如果 \(lson\) 没有进行更改,那么我们 \(rt_i\) 这个东西直接指向 \(rt_{i - 1}\) 里面的这个点,否则我们动态开点,每次新开一个位置。
Day 2
依旧是数据结构的一天
-
P3293 [SCOI2016] 美味。
异或是一个神奇的计算方法,我们可以拆位。
\(b \oplus (a_i + x)\),我们从高位到低位进行考虑。假设现在第 \(k\) 位上是 \(1\),我们根据异或的性质可以算出 \(a_i + x\) 这一位上是 \(0\) 还是 \(1\)。如果这样的话,我们直接处理在 \([l, r]\) 中的每一个 \(a_i + x\) 是否在这个 \(k\) 位区间之内即可。使用可持久化线段树进行优化。 -
P2839 [国家集训队] middle。
我们先把 \(a_i\) 离散化,对于一颗可持久化线段树,我们钦定 \(rt_{a_i}\) 代表 \(x < a_i\) 设置为 \(-1\),\(x = a_i\) 设置为 \(0\),\(x > a_i\) 的设置为 \(1\),然后我们发现每次指挥修改 \(2\) 个点。
同时,我们发现在区间 \([b + 1, c - 1]\) 这一段区间一定会取到,剩下的我们只需要在转化成 \(-1\) 和 \(1\) 的区间上面找到前缀和后缀最大值即可。 -
P3224 [HNOI2012] 永无乡。
算是半个板子题,只需要线段树合并以及可持久化线段树。
其实,这个线段树合并还是比较简单的。
假设我们现在要合并两个节点 \(u\) 和 \(v\)。
如果 \(u\) 和 \(v\) 中有一个节点是空的(在原线段树中没有),那么我们直接返回另一个即可。
否则,我们就递归合并左儿子和右儿子。 -
P4556 【模板】线段树合并 / [Vani 有约会] 雨天的尾巴。
我们发现,设 \(f_{u, i}\) 表示第 \(u\) 个节点表示有 \(i\) 的个数。我们发现, \(f_{u, i} = \sum f_{v, i} + a_{u, i}\),其中 \(a_{u, i}\) 表示自身贡献。接下来,我们发现这个 \(f_{u, i}\) 的计算过程类似于线段树合并,所以我们灵机一动,把这个过程使用类似线段树合并的方式解决。这样不就孑孓了。
yaoxi:大家都说这个是线段树合并板子,但是我觉得是上一个哎。
-
P2824 [HEOI2016/TJOI2016] 排序。
为数不多的简单题。我们发现,这个东西仅仅询问一次,所以我们不妨直接二分,剩下的就类似于把 \(0\) 和 \(1\) 进行重排即可。 -
P3521 [POI 2011] ROT-Tree Rotations。
线段树合并。我们考虑修改 merge 函数,因为我们发现,如果 \(x\) 是 \(u\) 中的数,\(y\) 是 \(v\) 中的数,那么 \(x < y\) 或者 \(x > y\) 的数量我们可以通过 \(st_{lson_u} \times st_{rson_v}\) 或者其他数据来计算,这样只需要轻松修改一下就可以了。 -
P3384 【模板】重链剖分 / 树链剖分。
经典树链剖分。简单介绍一下什么是树链剖分。这个分为两种,一种是重链剖分,一种是长链剖分。这里重点介绍重链。
我们设 \(son_u\) 表示所有的儿子 \(v\) 中的 \(size\) 最大的儿子。那么,从一个 \(top_u\) 到它的最低端的就叫做重链。然后就没了。重链剖分一般会借助线段树进行修改,这个东西比较快的原因是因为重链的数量会是 \(O(\log n)\) 级别的。因为假设 \(u\) 有两个儿子 \(v1\) 和 \(v2\),那么 \(size_{v1} > size_{v2}\),我们可以得到 \(size_u = size_{v1} + size_{v2} + 1 > 2 \times size_{v2}\)。所以,这个重链的数量是 $ O(\log n)$ 级别的。剩下的我们只需要统计一下 dfs 序,通过线段树来维护即可。 -
P2680 [NOIP 2015 提高组] 运输计划。
典。树链剖分经典操作。看到要求的最小值,不妨考虑二分。假设我们现在 check 长度为 \(mid\) 的是否合法。对于每一条最短路径 \(len\),如果 \(len \le mid\) 那么我们就可以直接不管;剩下的我们直接取交集,在上面是否存在一个 \(len - mid\) 或者更长的边,如果存在即为合法,否则就不合法。
同学:老师这和树链剖分有关系吗?
yaoxi:没有关系。
- P4211 [LNOI2014] LCA。
神奇题目。
我们发现这个 \(dep_{LCA(x, y)}\) 并不好求。那么,我们充分发扬人类智慧,把 \(1\) 到 \(x\) 的路径上的边权全都 \(+1\),然后直接查询 \(y\) 到根节点的路径即可完成。
接下来,我们考虑 \(\sum_{i = l}^{r} dep_{LCA(i, z)}\) 的值等于什么。容易发现,\(\sum_{i = 1}^{r} dep_{LCA(i, z)} - \sum_{i = 1}^{l - 1} dep_{LCA(i, z)}\)。
然后,我们把这些询问离线下来,再随随便便处理一下就行了。
yaoxi:想我这样自己做过的题基本上都记不得了的都能记得这道题。
同学:哎,这个难道点分治?
yaoxi:不是,但是话说回来,一会就要讲点分治。
同学:不是晚上讲吗?
yaoxi:这不也是快到晚上了吗(此时是 15:44)。
不用点分治做法。
我们设 \(len_u\) 表示 \(1\) 到 \(u\) 的带权路径,\(dep_u\) 表示深度。
接下来,使用 map 对于每一个 \(len_u\) 映射到一个 \(dep_u\)。接下来,我们考虑对于两个 \(u\) 和 \(v\) 的子树进行合并。假设在 \(v\) 里面有一个点 \(\alpha\),那么我们查询 map 中是否存在 \(len_{\beta} = k - len_{\alpha} + 2 \times len_u\)。如果存在,那么就用出我们经典的式子 \(dep_{\alpha} + dep_{\beta} - 2 \times dep_{LCA(\alpha, \beta)}\) 更新最小值即可。这里使用启发式合并,也就是每次把小的合并到大的上面,这样的复杂度就是 \(O(\log n)\) 级别,再加上一个 map 的复杂度,那么总的就应该是 \(O(n \log^2n)\)。
yaoxi:常数是不是有点大?没关系,\(3\) 秒呢。
- P3806 【模板】点分治。
点分治,一种神奇的思想。我们根据重心的定义可得,每一个树里面会有 \(1\) 或 \(2\) 个重心。那么,我们选择任意一个,那么我们把它的所有子树的重心拿出来再次放到下一层。那么,每层至少是上面一层的 \(2\) 倍,所以复杂度也就是 \(O(\log n)\) 级别的。我们可以用点分治干什么呢?很简单,每次我们都把 \(x\) 和 \(y\) 找到最低一层的 \(w\),使得 \(w\) 包含着 \(x\) 和 \(y\),一般可以用来进行树的权值修改。
Day 3
-
P4180 [BJWC2010] 严格次小生成树。
对于严格次小生成树,我们发现,这个树一定是在原有的生成树上面更改一条边得到的。具体的,对于一条边 \((u, v, w)\),我们考虑把这个替换成一条 \((a, b, c)\) 的边。而且,这个替换的越大越好。上述过程中可以使用倍增或者树剖维护,复杂度 \(O(n \log n)\)。 -
P14415 [JOISC 2015] 遗产继承 / Inheritance。
神奇题目。
注意到“边权不等”,所以说明最小生成树是唯一的。我们把边权排序,可以得到 \((u, v, w)\) 的边。接下来,我们考虑二分,二分到第一个 \(i\) 使得 \((u, v)\) 在 \(i\) 连通块中不成环。
证明:假设在 \(i\) 处不成环,但是在 \(j\) 处成环,那么假设 \((x, y, z)\) 是使得成环的边,且 \(z > w\)。那么,我们可得,\((x, y)\) 在连通块 \(i\) 中也一定不联通。所以,与假设不符,故原命题得证。
然后就是二分加上并查集 check,复杂度是 \(O(m \log K \alpha(n) + m \log m)\)。 -
P5905 【模板】全源最短路(Johnson)。
比较高效的全源最短路问题。我们发现,如果我们跑 \(n\) 次最短路,那么复杂度就是 \(O(nm\log m)\);那么,接下来我们考虑建立超级源点 \(0\),对于边 \((u, v, w)\),满足 \(h_v \le h_u + w\),建立边权为 \(h_u - h_v + w\),保证非负性,接下来我们就跑 Dijkstra 即可。 -
CF1473E Minimum Path。
由于最大值和最小值是不好的,我们遇到一条边直接钦定为最大值或者最小值,因为这样一定是优的,加上一个最小值或者减掉一个更大的值都是不如这样的。所以我们设 \(dis_{u, 0/1, 0/1}\) 表示是否钦定过最小值与最大值,这样就形成了一个类似分层图的东西,再去做就行了。 -
CF1693C Keshi in Search of AmShZ。
考虑 DP。我们设 \(f_u\) 表示 \(u\) 到 \(n\) 的答案。我们可以轻松得到转移方程:
就这么简单。
- P7515 [省选联考 2021 A 卷] 矩阵游戏。
神奇题目。
我们发现,我们只要钦定了第一行和第一列,我们就可以表示出 \(a_{x, y}\)。形式化的,我们可以发现
这里有三个式子,不好直接进行差分约束。
我们考虑换元:\({a}'_{1, y} = (-1)^{y + 1} \times a_{1, 1} + a_{1, y}\)。则原式等于 \((-1)^{x + 1} \times {a}'_{1, y} + (-1)^{y + 1} \times a_{x, 1}\)。因为 \(x\) 和 \(y\) 不一定是奇偶性不同的,所以我们不妨令 \(b_y = (-1)^{y} \times {a}'_{1, y}\),\(c_x = (-1)^{x + 1} \times a_{x, 1}\),所以原式也就是 \((-1)^{x + y + 1} \times b_y + (-1) ^ {x + y + 2} \times c_x\),这样 \(c_x\) 和 \(b_y\) 一定不同号,这样就可以进行差分约束。
浙公网安备 33010602011771号