2026.9 树上专题做题记录
CF1844G Tree Weights
先给所有边的边权赋成 \(1\),然后 \(d_i \gets d_i - dis(i,i+1)\)。
找到当前 \(d\) 的最小值,设其为 \(d_{x}\)。在 \(P(x,x+1)\) 上找一条边 \((u,v)\)(没被使用的),将 \(w(u,v)\) 设成 \(d_x+1\)。并对所有经过 \((u,v)\) 的 \(P(y,y+1)\),将 \(d_y\) 减去 \(d_{x}\)。最后删去 \(d_x\),并将 \((u,v)\) 标记为已使用。
如果能给每对 \((i,i+1)\) 都分配一条边 \((u,v)\),那么一定是存在合法解的(不考虑 \(d_i < dis(i,i+1)\))。因为这样做保证了任意时刻 \(d_i\ge 0\),且轮到 \((i,i+1)\) 时让 \(d_i\) 变成了 \(0\)。
尝试通过删叶子的方式来分配。以 \(1\) 为树根。随便找一个叶子 \(u\):
- 新建一个点 \(c\)。
- 若 \(u-1\) 不在 \(u\) 子树内。连边 \((c,u-1)\)。
- 若 \(u+1\) 不在 \(u\) 子树内。连边 \((c,u)\)。
那么会得到若干条链。
对于某条链的前两个点 \((c,u)\),如果将 \(c\) 对应的边分配给 \((u,u+1)\),那么后面就都是确定的。
如果出现某条链 \(c\) 的数量与 \(u\) 的数量不同,显然就无解了。
这样分配的时间复杂度 \(O(n)\)。但是模拟的过程有点困难了。
原来不是这样做吗。
考虑以 \(1\) 为根。记 \(x_i\) 为 \(i\) 到 \(1\) 边权和。那么限制为:
- \(x_i + x_{i+1}-2x_{\text{lca}(i,i+1)}=d_i\)。
已知 \(x_1 = 0\)。从小到大枚举 \(i\),但问题是可能 \(\text{lca}(i,i+1) \ge i+1\)。
注意到 \(x_{\text{lca}(i,i+1)}\) 前面有个 \(2\) 的系数,想到先对 \(2\) 取模。变成:
- \((x_i + x_{i+1})\bmod 2=d_i\bmod 2\)。
此时就可以推出 \(x_{2\sim n}\bmod 2\) 的值。再考虑对 \(4\) 取模,变成:
- \((x_i + x_{i+1} -2(x_{\text{lca}(i,i+1)}\bmod 2))\bmod 4=d_i\bmod 4\)。
同样可以推出 \(x_{2\sim n}\bmod 4\) 的值。
重复下去,就可以知道 \(x_{i}\bmod V\) 的值。当 \(V> x_i\) 时就不再需要继续推了。
最后再 check 一下是否满足边权都 \(\ge 1\) 即可。时间复杂度 \(O(n\log n + n\log V)\)。
QOJ837 Giant Penguin
随便找棵 DFS 树然后点分治。
对于当前分治中心 \(u\),因为需要处理的信息必须跨过 \(u\),所以有用的非树边只有 \(O(k)\) 条(一条非树边贡献一个环)。而对于点 \(x\) 到 \(y\) 的最短路,可以枚举一个必经点 \(c\),一定存在一个 \(c\) 使得 \(\text{dis}(x,y)=\text{dis}(x,c)+\text{dis}(c,y)\)。而这样的 \(c\) 只需要取 \(u\) 和这 \(O(k)\) 条非树边的端点。
那么以这 \(2k+1\) 个点为起点 BFS 得到最短路,查询时直接枚举这个 \(c\) 即可。
时间复杂度 \(O(nk\log n)\)。
CF1458F Range Diameter Sum
树上圆理论。
- 记 \(f(u,r)\) 为距离 \(u\) 不超过 \(r\) 的点构成的邻域。
- 设 \(c(S)=f(u,r)\) 为包含点集 \(S\) 的最小邻域。这里令 \(x,y\) 为 \(S\) 中最远两个点,\(u\) 为 \(x,y\) 路径中点(可能是边的中点),\(d\) 为 \(x,y\) 的距离。则 \(r = \frac{d}{2}\)。即 \(c(S) = f(u,\frac{d}{2})\)。
有一些性质:
- 邻域 \(f(u_1,r_1)\) 包含邻域 \(f(u_2,r_2)\),当且仅当 \(r_1\ge r_2+\text{dis}(u_1,u_2)\)。
- 对于合并两个点集 \(S_1,S_2\) 得到 \(c(S_1\cup S_2)\),有:
- \(S_1\) 包含 \(S_2\)。\(c(S_1\cup S_2)=c(S_1)\)。
- \(S_2\) 包含 \(S_1\)。\(c(S_1\cup S_2)=c(S_2)\)。
- \(S_{1}\) 与 \(S_2\) 无包含关系。令 \(d = \text{dis}(u_1,u_2)\),则 \(c(S_1\cup S_2)=f(\text{move}(u_1,u_2,\frac{d-r_1+r_2}{2}),\frac{d+r_1+r_2}{2})\)。其中 \(\text{move}(u,v,w)\) 为 \(u\) 向 \(v\) 移动 \(w\) 的距离到达的点。
- 对于点集 \(S\),任意一个点 \(v\) 到 \(S\) 中最远点的距离为 \(\text{dis}(u,v) + r\)(\(c(S)=f(u,r)\))。
对于这题,考虑分治。
记 \(s(i)\) 为 \(i\) 到 \(\text{mid}\) 构成的点集。
如果已知 \(c(\{l,l+1,\dots,r\})=c(s(l)\cup s(r)) = f(u,R)\),那么 \(\text{diam}(l,r) = 2R\)。
枚举 \(l\),维护指针 \(i,j\) 使得:
- \(r\in [\text{mid}+1,i]\) 均有 \(c(s(l))\) 包含 \(c(s(r))\)。设 \(c(s(l))=f(u,R)\),则 \(\text{diam}(l,r)=2R\)。
- \(r\in [i+1,j]\) 均有 \(c(s(l))\) 与 \(c(s(r))\) 无包含关系。设 \(c(s(l))=f(u_1,R_1),c(s(r))=f(u_2,R_2)\),则 \(\text{diam}(l,r)=R_1+R_2+\text{dis}(u_1,u_2)\)。
- \(r\in [j+1,r_0]\) 均有 \(c(s(r))\) 包含 \(c(s(l))\)。设 \(c(s(r))=f(u,R)\),则 \(\text{diam}(l,r)=2R\)。
先考虑维护出 \(c(s(i))\),首先 \(c(s(\text{mid}))=f(\text{mid},0)\)。以 \(c(s(l))\) 举例,设 \(c(s(l+1))=f(u,R)\):
- \(\text{dis}(l,u)\le R\)。则 \(c(s(l))=c(s(l+1))\)。
- \(\text{dis}(l,u)>R\)。则 \(c(s(l)) = f(\text{move}(l,u,\frac{\text{dis}(l,u)-0+R}{2}),\frac{\text{dis}(l,u)+0+R}{2})\)。
维护出 \(c(s(i))\) 后情况 \(1,3\) 都是简单的。情况 \(2\) 中 \(R_1+R_2\) 也是简单的。对于 \(\text{dis}(u_1,u_2)\),相当于是查询某个点到当前所有关键点距离和,点分树即可。
那么只需要实现 \(\text{move}\) 函数,\(\text{dis}\) 函数,点分树和分治。为了方便计算 \(R\),可以给每条边中间加一个虚点,这样只需要最后答案除以 \(2\)。
整体时间复杂度 \(O(n\log^2 n)\)。
CF1168D Anagram Paths
考虑先判定一棵树是否是变为字母异位树。
- 所有叶子深度相同。
- 记 \(cnt_{u,x}\) 为 \(u\) 到子树叶子中 \(x\) 出现次数的最大值。那么需要满足 \(\sum\limits_{x='a'}^{'z'}cnt_{u,x}\le \text{mdep}(u)-\text{dep}(u)\)。
容易发现,对于 \(f(c)\) 其实就等于 \(\text{mdep}(1)-\text{dep}(1) - \sum\limits_{x='a'}^{'z'}cnt_{1,x} + cnt_{1,c}\)。
那么有:\(\sum\limits_{c=1}^{26}f(c) = 351(\text{mdep}(1)-\sum\limits_{x=1}^{26}cnt_{1,x})+\sum\limits_{x=1}^{26}x\times cnt_{1,x}\)。
每个点上维护 \(cnt_{u,x}\)。那么修改点 \(p\) 和 \(fa_p\) 之间的字符影响的就是一条 \(p\) 到某个祖先的链。二分这个祖先即可。然后就是对一条链的 \(cnt_{u,x}\) 增加或减少 \(1\)。最后整体维护全局最小值。需要 \(27\) 棵线段树。
时间复杂度 \(O(n|\sum|\log n + n\log^2 n)\)。这个也可以做到一个 \(\log\)。
注意到因为叶子深度相同,所以一个点到根中有两个儿子的祖先只有 \(O(\sqrt{n})\) 个。那么暴力跳这些祖先的时间复杂度就是 \(O(n\sqrt{n}+n|\sum|)\) 的。
P10789 [NOI2024] 登山
先将 \(a\) 序列简化,即删去所有 \(p_{a_j}=a_{j-1}\) 的 \(a_j\)。得到的应该是 \(x\) 到 \(1\) 路径上的某些点,且深度单调递减。
再在 \(a_i\) 和 \(a_{i+1}\) 中添加若干个休息的点,设 \(a_i\) 与 \(a_{i+1}\) 中添加的最后一个休息点为 \(p\)(没有则令 \(p=a_i\))。考虑 \(a_{i+1}\) 的合法条件:
- \(d_{a_{i+1}}<\min\limits_{u\in P(p,a_{i})}^{}(d_u-h_u)\)。
- \(d_p - r_{p}\le d_{a_{i+1}} \le d_{p} -l_p\)。
定义状态函数 \(f_{u}\) 为从 \(u\) 出发的方案数。那么枚举 \(u\) 再枚举 \(p\),可以得到合法的下一个冲刺点范围,通过前缀和可以 \(O(1)\) 得到方案数之和。这样复杂度是 \(O(n^2)\) 的。
先考虑 \(l_i = r_i\) 怎么做。
对于 \(p\),设下一个冲刺点为 \(x\)。则 \(d_{p}-r_p \le d_x \le d_p-l_p\),也就是 \(d_x = d_p-l_p\)。此时满足 \(d_x < \min\limits_{v\in P(p,u)}^{}(d_v - h_v)\) 的 \(u\) 应该是从 \(P(p,1)\) 的一段前缀。可以二分找到这个前缀的结尾 \(u_0\),那么所有 \(u\in P(p,u_0)\) 的 \(f_u\) 都可以得到 \(f_{x}\) 的贡献。显然 \(d_x < d_{u_0}\) 所以不会转移出错。
具体做法就是 DFS 一遍,得到 \(f_{x}\) 之后将 \(x\) 子树中所有满足 \(d_{x} = d_{p}-l_p\) 的 \(p\) 拿出来,对每个 \(p\) 找到这样的 \(u_0\),然后将 \(u\in P(p,u_0)\) 的 \(f_u\) 都加上 \(f_x\)。复杂度 \(O(n\log^2 n)\)。
如果 \(l_i \ne r_i\)。
设 \(g_{u}=\sum\limits_{x\in P(u,1)}^{}f(x)\),相当于一个前缀和。对于 \(p\),设转移点为 \(u\)。条件变成 \(d_{p}-r_{p} \le d_x < \min(d_p-l_p+1,\min\limits_{v\in P(p,u)}^{}(d_v-h_v))\)。记 \(h(p,u)=\min(d_p-l_p+1,\min\limits_{v\in P(p,u)}^{}(d_v-h_v))\)。当 \(d_p-r_p \le h(p,u)\) 时 \(f_u\) 得到 \(g_{\text{move}(p,h(p,u)-1)}-g_{fa_{\text{move}(p,d_p-r_p)}}\) 的贡献。其中 \(\text{move}(u,x)\) 为 \(P(u,1)\) 中深度为 \(x\) 的点编号。
拆成两部分做。
\(g_{fa_{\text{move}(p,d_{p}-r_p)}}\) 就相当于 \(l_i=r_i\) 的情况。在得到 \(x = \text{move}(p,d_p-r_p)\) 的信息后枚举 \(p\)。
\(g_{\text{move}(p,h(p,u)-1)}\) 这部分可以考虑放到 \(h(p,u)=d_v - h_v\) 的 \(v\) 这里算。
- \(h(p,u) = d_p-l_p+1\)。找到深度最小的 \(u_1\),使得 \(h(p,u) = d_{p} -l_p+1\)。那么枚举 \(p\) 得到 \(u_0\) 后只需要与 \(u_1\) 取深度较大者即可。
- \(h(p,u)<d_p-l_p+1\)。考虑 \(i\) 向 \(i\) 祖先中第一个满足 \(d_j -h_j < d_i - h_i\) 的 \(j\) 连边,得到很多棵树。定义 \(cnt_v\) 为放到 \(v\) 这里来算的 \(p\) 的数量。不难发现 \(cnt_v\) 等价于新的树中 \(v\) 子树满足 \(d_p - r_p \le d_v - h_v < d_p - l_p+1\) 的 \(p\) 的数量。由于新树上 \(d-h\) 是单调的,所以也可以对每个 \(p\) 二分找到这样的 \(v\) 所在链。树上差分就可以维护出 \(cnt_v\)。最后还是在得到 \(x\) 的信息后枚举子树中所有 \(d_v - h_v = d_x\) 的 \(v\),让后对 \(u\in P(v, u_0)\) 的 \(f_u\) 增加 \(g_{x}\times cnt_v\)。
整体时间复杂度 \(O(n\log^2 n)\)。
链加单点查不需要树剖。直接 dfn 序加就是 \(O(n\log n)\) 的了。。。
P16435 [APIO 2026 中国赛区] 集宝
记 \(f(u,r)\) 为与 \(u\) 距离不超过 \(r\) 的邻域。
对于暴力,显然就是每次走到 \(y\in f(a_{i+1},d_{i+1})\) 中 \(\text{dis}(x,y)\) 最小的那个点上。时间复杂度 \(O(nq\log n)\)。
发现对于相邻两个 \(f(a_i,d_i),f(a_{i+1},d_{i+1})\) 来说,如果 \(f(a_i,d_i)\cap f(a_{i+1},d_{i+1})\not= \emptyset\),将它们缩成它们的交 \(f(u,c)\) 对答案是没有影响的。
又发现这个合并顺序是没影响的,也就是如果 \(i\) 和 \(i+1\) 合并之后不能再和 \(i+2\) 合并;如果 \(i+1\) 和 \(i+2\) 合并之后不能再和 \(i\) 合并,这两种情况都是正确的。
那么考虑维护这些树上圆。具体地,维护 \(s,t,d,r\) 分别表示路径起点,路径终点,路径长度,经过的树上圆交的半径。
有定义:
- 对于一个点 \(u\)。\(s = u,t=u,d=0,r=0\)。
- 对于一个 \((a_i,d_i)\)。\(s = a_i, t = a_i, d = 0, r = d_i\)。
合并 \((s_1,t_1,d_1,r_1)\) 和 \((s_2,t_2,d_2,r_2)\) 到 \((s,t,d,r)\):
- 二者均为点。\((s,t,d,r) = (u,v,d_1+d_2+\text{dis}(t_1,s_2),0)\)。当 \(d_1 > 0\) 时 \(u = s_1\);当 \(d_1 = 0\) 时 \(u = \text{move}(t_1,s_2,r_1)\)。当 \(d_2 > 0\) 时 \(v = t_2\);当 \(d_2 = 0\) 时 \(v=\text{move}(s_2,t_1,r_2)\)。
- 前者是点,后者是圆的交。
- \(t_1 \in f(s_2,r_2)\)。\((s,t,d,r) = (s_1,t_1,d_1+d_2,0)\)。
- \(t_1\notin f(s_2,r_2)\)。\((s,t,d,r) = (u,v,d_1+d_2+\text{dis}(t_1,s_2)-r_2,0)\)。当 \(d_1 > 0\) 时 \(u = s_1\);当 \(d_1 = 0\) 时 \(u = \text{move}(t_1,s_2,r_1)\)。当 \(d_2 > 0\) 时 \(v = t_2\);当 \(d_2 = 0\) 时 \(v=\text{move}(s_2,t_1,r_2)\)。
- 后者是点,前者是圆的交。
- \(s_2\in f(t_1,r_1)\)。\((s,t,d,r) = (s_2,t_2,d_1+d_2,0)\)。
- \(s_2\notin f(t_1,r_1)\)。\((s,t,d,r) = (u,v,d_1+d_2+\text{dis}(t_1,s_2)-r_1,0)\)。当 \(d_1 > 0\) 时 \(u = s_1\);当 \(d_1 = 0\) 时 \(u = \text{move}(t_1,s_2,r_1)\)。当 \(d_2 > 0\) 时 \(v = t_2\);当 \(d_2 = 0\) 时 \(v=\text{move}(s_2,t_1,r_2)\)。
- 二者均为圆的交。
- 前者包含后者。\((s,t,d,r) = (s_2,t_2,d_1+d_2,r_2)\)。
- 后者包含前者。\((s,t,d,r) = (s_1,t_1,d_1+d_2,r_1)\)。
- 二者相交。相交得到的圆的半径为 \(R =\frac{r_1+r_2-\text{dis}(t_1,s_2)}{2}\),圆心为 \(v = \text{move}(t_1,s_2,r_1 -R)\)。有 \((s,t,d,r) = (v,v,d_1+d_2,R)\)。
- 二者不相交。可以看作移动到后者时就变成一个点了,因为如果不看作点可能还与后面的圆又有交,此时无法确定位置与距离,但基础暴力就是走到后者邻域中最近点,所以是可行的。\((s,t,d,r) = (u,v,d_1+d_2+\text{dis}(t_1,s_2)-r_1-r_2,0)\)。当 \(d_1 > 0\) 时 \(u = s_1\);当 \(d_1 = 0\) 时 \(u = \text{move}(t_1,s_2,r_1)\)。当 \(d_2 > 0\) 时 \(v = t_2\);当 \(d_2 = 0\) 时 \(v=\text{move}(s_2,t_1,r_2)\)。
既然能合并,就可以直接倍增维护了。时间复杂度 \(O((n+q)\log^2 n)\)。
CF1442E Black, White and Grey Tree
如果没有灰色点。
将同色连通块缩成一个点,得到一棵相邻两个点颜色都不同的树。
这个相当于选择一个点作为根,每次删掉所有叶子。那么操作次数就是到根距离的最大值加 \(1\)。
这个选择直径中点是最优的,记 \(len\) 为直径长度(边数)。那么答案等于 \(\lceil\frac{len}{2}\rceil+1\)。
如果有灰色点。发现灰色点是没有用的,可以直接删去。考虑证明:
如果灰色点有用,说明存在路径 \(u\to v \to w\),使得 \(u,w\) 不是灰色点,\(v\) 是灰色点。且 \(v\) 存在第三条边 \((v,k)\),满足在忽略 \(v\) 后得到的直径经过 \(u\to w\),但实际上 \(v\) 变成的颜色(\(v\) 不对这条直径产生贡献的颜色唯一)让真正的直径经过 \(u\to k\)。
分情况讨论:
- \(u,w\) 同色。此时 \(v\) 与 \(u\) 同色。
- \(u,k\) 异色。实际上 \(u,v\) 会缩成一个点,\(v\) 不产生额外贡献。
- \(u,k\) 同色。\(u,v,k\) 会缩成一个点,\(v\) 不额外产生贡献。
- \(u,w\) 异色。此时 \(v\) 可以与 \(u\) 或 \(w\) 同色。
- \(u,k\) 异色。当 \(v,k\) 同色时不产生额外贡献。
- \(u,k\) 同色。当 \(v,k\) 同色时不产生额外贡献。
所以直径不会从 \(u\to w\) 变成 \(u\to k\)。那么删去 \(v\) 无影响。
并查集维护同色连通块即可。时间复杂度 \(O(n)\)。
CF1712F Triameter
记 \(f(u)\) 为 \(u\) 到最近一个叶子的距离。
考虑对于一个询问二分答案,问题变成判断是否存在一对点 \((u,v)\),使得 \(\text{d}(u,v)\ge mid\)。
显然 \(\text{d}(u,v)=\min(\text{dis}(u,v),f(u)+f(v)+x)\)。
枚举 \(u\),变成判断是否存在 \(v\),使得满足以下条件:
- \(f(v)\ge mid - x - f(u)\)。
- \(\text{dis}(u,v)\ge mid\)。
先一遍 DFS 预处理 \(f(i)\),并将 \(f(i)\) 从大到小排序。设排序后第 \(i\) 个为点 \(p_i\)。问题变成判断是否存在 \(i\in [1,k]\),使得 \(\text{dis}(p_i,u)\ge mid\)。直接维护直径。
使用 \(O(1)\) 查询的 \(\text{lca}\) 单次 check 就是 \(O(n)\) 的。
整体时间复杂度 \(O(n\log n + nq\log n)\)。
考虑去掉二分。从前往后枚举 \(i\),同时维护当前的 \(ans\)。尝试将 \(ans\) 增加 \(1\)。此时可以用指针维护出满足 \(f(v)\ge (ans+1)-x-f(i)\) 的最大的 \(v\)(因为 \(ans\) 单调不减,\(f(i)\) 单调不增)。这样问题就又变成判断是否存在 \(j\in [1,v]\),使得 \(\text{dis}(p_i,p_j)\ge mid\) 了。
时间复杂度 \(O(n\log n + nq)\)。
AT_arc087_d [ARC087F] Squirrel Migration
注意到让尽可能多的路径经过同一个点是不劣的。
比如要让尽可能多的路径经过 \(u\)。以 \(u\) 为根,若 \(u\) 的两个儿子 \(z_1,z_2\) 子树中存在两对点 \((x_1,y_1),(x_2,y_2)\),满足 \(x_1,y_1\in T(z_1);x_2,y_2\in T(z_2)\),将点对调整为 \((x_1,y_2),(y_1,x_2)\) 不劣。
注意到当 \(u\) 为树的重心时不存在绝对众数,此时一定可以让所有路径都经过 \(u\)。
那么以树的重心为根。将根的每个儿子子树都染色成这个儿子的编号,令根为无色点。
问题变成给定每个点的颜色 \(col_{1\sim n}\),求排列 \(p_{1\sim n}\) 的数量。满足 \(col_{p_i}\ne col_i\) 或 \(col_{p_i}=0\)(只有根的 \(col\) 是 \(0\))。
考虑容斥。设 \(G(k)\) 为钦定 \(k\) 个 \(i\) 满足 \(col_{p_i}=col_i\) 且 \(col_{p_i} \ne 0\) 时的方案数。则答案等于 \(\sum\limits_{k}^{}(-1)^{k}G(k)\)。
定义状态函数 \(f_{i,j}\) 为考虑完前 \(i\) 种颜色,有 \(j\) 个位置被钦定的方案数。记 \(cnt_i\) 为颜色 \(i\) 的数量。转移为:\(f_{i,j+x}\gets f_{i-1,j}\times \binom{cnt_i}{x}\times (cnt_i)^{\underline{x}}\)。
最后 \(G(k) = f_{n,k}\times (n-k)!\)。时间复杂度 \(O(n^2)\)。
P13695 [CEOI 2025] theseus
注意到 \(01\) 状态可以用来描述边的方向。
定义 \((u,v)\) 标记为 \(0\) 表示边 \(u\to v\);标记为 \(1\) 表示边 \(v \to u\)。
以 \(T\) 为根跑 BFS 得到每个点到 \(T\) 的最短路 \(dis_i\)。按照 \(dis\) 从小到大分层。
考虑对于一条边 \((u,v)\):
- \(dis_u < dis_{v}\)。标记为 \(1\)。
- \(dis_u > dis_v\)。标记为 \(0\)。
- \(dis_u = dis_v\)。不太好处理。
如果 \(dis_{u}= dis_{v}\) 的边直接按照 \(u,v\) 大小连,这样可能需要 \(\min + O(n)\) 次查询。
考虑启发式合并。具体的,按照深度从大到小枚举,对于一条边 \((u,v)\):
- \(dis_{u}> dis_{v}\)。将 \(u\) 合并到 \(v\) 上面去。标记为 \(0\),并清空 \(u\)。
- \(dis_u = dis_v\)。将小的合并到大的上面去,并清空小的。
这样从一个点出发,每次如果都能知道它下一次合并到哪个点,那么:
- 向上合并。显然走的最短路。
- 向左右合并。因为合并后 \(siz\) 至少翻倍,所以只会出现 \(O(\log n)\) 次。
但我们并不能存下每个点下一次合并到哪。
考虑对于同深度的边,按照 \(u\) 从大到小枚举合并。这样对于一条边 \((u,v)\),如果 \(dis_u = dis_v\),一定有 \(u > v\),且:
- \(siz_v = 0\)。说明之前一个更大的 \(u'\) 将 \(v\) 合并了。如果走出边中编号最大的,是会走到 \(u’\) 或一个深度更小的点的。满足要求。
- \(siz_v>0\)。说明还没合并。此时 \(u\) 是最大的满足 \(dis_{u}=dis_v\) 的有边的点,走出边中编号最大的要么走到 \(u\) 要么走到深度更小的点。
时间复杂度 \(O(n\log n)\)。
CF1039D You Are Given a Tree
考虑对于一个 \(k\) 怎么做。
贪心地,维护 \(f_{u}\) 表示 \(u\) 会对父亲贡献多少个点。记 \(x,y\) 为儿子 \(f\) 的最大值与次大值,有:
- \(x+y+1\ge k\)。\(f_u=0\),答案增加 \(1\)。
- \(x+y+1<k\)。\(f_u = x+1\)。
注意到对于情况 \(1\),只会有 \(O(\frac{n}{k})\) 次。那么对于 \(1\le k \le n\),总次数是 \(O(n\log n)\) 的。
这启发我们放一起做。
维护 \(f_{u,k}\) 为当 \(k\) 为这个值时,\(u\) 会对父亲贡献多少个点。记 \(g(u)\) 为 \(u\) 到最深的叶子路径上包含的点数。
不难发现,当 \(k \ge 2g(u)\) 时一定有 \(f_{u,k}=g(u)\)。那么考虑长剖。
对于一个 \(u\):
-
继承重儿子信息。
-
对于 \(u\) 的轻儿子,维护 \(h_k = (a,b)\) 表示 \(f_k\) 的最大值、次大值。因为是长剖,所以可以暴力求,只有 \(k\in (2g(u),2g'(u)]\) 时 \(h_k = (g'(u)-1,g''(u)-1)\)。其中 \(g'(u)\) 为 \(u\) 到次深的叶子路径上包含的点数,\(g''(u)\) 为第三深。
-
更新信息。
-
首先对于 \(k\in (2g'(u),1)\) 可以求出重儿子 \(f_{k}\),设 \(h_{k} = (a,b)\)。那么相当于取 \(f_k,a,b\) 的前 \(2\) 大作为 \(x,y\),然后暴力修改 \(f_{k}\)。
-
其次对于 \(k\in (2g(u),2g'(u)]\),分两种情况讨论:
- \(f_k + a + 1 \ge k\)。相当于找到区间中所有满足 \(k-f_k \le a+1\) 的 \(k\)。线段树维护区间 \(\min\) 即可。
- \(a+b+1\ge k\)。有 \(k\in (2g(u),\min(2g'(u),a+b+1)]\)。
显然,对于一个产生贡献的 \(f_k\),最多会被找到 \(2\) 次,不影响时间复杂度。最后再对 \(k\in (2g(u),2g'(u)]\) 执行 \(f_k\gets \max(f_k,a)+1\) 即可。
-
那么线段树需要维护:区间查询 \(\min\),区间 chmax,区间加 \(1\),单点修改。
整体时间复杂度 \(O(n\log^2 n)\)。
CF2161F SubMST
枚举 \((u,v)\),考虑边 \((u,v)\) 什么情况下会在最小生成树上。
设子集为 \(S\),首先两个必要条件是:
- \(u,v\in S\)。
- \(\nexists x\in S, \max(\text{dis}(x,u),\text{dis}(x,v)) < \text{dis}(u,v)\)。
如果直接对这个算会将 \(\max(\text{dis}(x,u),\text{dis}(x,v))=\text{dis}(u,v)\) 的算重,但这个是小问题。
对于条件 \(2\),记 \(f(u,r)\) 为距离 \(u\) 不超过 \(r\) 的邻域,则需要满足 \(x\notin f(u,\text{dis}(u,v))\cap f(v,\text{dis}(u,v))\)。根据树上圆的性质,可知 \(f(u,\text{dis}(u,v))\cap f(v,\text{dis}(u,v))\) 也是一个邻域 \(f(w,r)\)。
先在每条边上加个虚点,令实点为原树上的点。
考虑枚举圆心 \(w\),以 \(w\) 为根。枚举深度 \(r\),按顺序依次加入深度为 \(r\) 的实点。记 \(cnt_r\) 为深度不超过 \(r\) 的实点数量,\(c\) 为在加入当前实点之前已经加入的深度为 \(r\) 的实点数量。则贡献为:\((2^{(c-d)}-1) \times 2^{n-cnt_{r-1}-c-1}\times r\),其中 \(d\) 为与当前实点在 \(w\) 的同一儿子子树且已经加入的实点数量。 这样钦定了 \(\max(\text{dis}(x,u),\text{dis}(x,v))=\text{dis}(u,v)\) 时加入点的顺序,所以不会算重。
时间复杂度 \(O(n^2)\)。
P11946 [KTSC 2025] 信竞天择 2 / evolution
因为是知道树的,所以考虑从下往上求解。
那么现在对于一个 \(u\),已知 \(u\) 每个儿子子树内部所有点的相对大小,现在需要合并所有儿子。
相当于现在合并两个大小分别为 \(a,b\) 的有序序列。
考虑两种做法:
- 直接归并 \(a,b\)。需要比较 \(|a| + |b| - 1\) 次。
- 因为 \(a,b\) 是有序的,所以可以考虑先找到 \(b_{\frac{|b|}{2}}\) 在 \(a\) 中的位置。这样 \([1,\frac{|b|}{2})\) 和 \((\frac{|b|}{2},|b|]\) 就被拆成两部分了。比较次数是 \(O(|b|\log\frac{|a|}{|b|})\) 的。
那么直接做,每次做比较次数小的那个就是对的。
P7563 [JOISC 2021] 最悪の記者 4 (Worst Reporter 4) (Day4)
\(i\) 向 \(a_i\) 连边得到内向基环树森林。
对于非环上点,要求点权不小于父亲点权;对于环上点,要求点权相同。
注意到当确定了点权不变的点时,剩下的点一定可以满足条件。那么定义状态函数 \(f_{u}\) 为当 \(u\) 点权不变时,\(u\) 子树节省代价的最大值。有:
- \(f_u = c_u + \sum\limits_{v\in son_u}^{}\max(f_{v}[h_v\ge h_u],g_{v,h_u})\)。
- \(g_{u,x}=\sum\limits_{v\in son_u}^{}\max(f_{v}[h_v\ge x],\max\limits_{y\ge x}^{}g_{v,y})\)。
其中 \(g_{u,x}\) 表示选择 \(u\) 子树中若干个不交的子树,使得每个选择子树的根都被保留且点权不小于 \(x\)。
直接线段树合并即可。需要维护:单点修改,合并,后缀 \(\max\)。
对于一棵基环树,记环上点为 \(p_1,p_2,\dots,p_k\),\(sum\) 为基环树所有点 \(c\) 的和。分情况讨论:
- 环上的点都不保留。答案为 \(sum - \sum\limits_{i=1}^{k}\sum\limits_{v\in son_{p_i}}^{}\max\limits_{x}^{}g_{v,x}\)。
- 有环上的点要保留。答案为 \(sum - \max\limits_{x}^{}(\sum\limits_{i=1}^{k}\max(f_{p_i}[h_{p_i}=x],\sum\limits_{v\in son_{p_i}}^{}\max\limits_{y\ge x}^{}g_{v,y}))\)。
线段树合并时间复杂度 \(O(n\log n)\)。
P10013 [集训队互测 2023] Tree Topological Order Counting
对于 \(u\) 计算答案,只需要满足 \(u\) 子树中的点都在 \(fa_u\) 之后就行了。
那么定义状态函数 \(f_{u,i}\) 为只考虑 \(u\) 子树外的点(包括 \(u\))且 \(u\) 的相对大小为 \(i\) 时的方案数。
记 \(g_u = siz_u!\prod\limits_{v\in T(u)}^{}\frac{1}{siz_v}\)。那么有:
- \(ans_u = \sum\limits_{x = 1}^{n}b_{x} \times f_{u,x}\times \binom{n-x}{siz_u-1}\times g_u\)。
对于转移,有:
- \(f_{u,i} = \sum\limits_{j<i}^{}f_{fa_u,j}\times (\prod\limits_{v\in son_{fa_u}\land v\ne u}^{}g_v)\times ((n-j-siz_u)! \prod\limits_{v\in son_{fa_u}\land v\ne u}^{}\frac{1}{siz_v!}\times \frac{1}{(n-siz_{fa_u}+1-j)!})\)。
时间复杂度 \(O(n^2)\)。
QOJ9700 英杯
定义状态函数 \(f_{u,x,y,0/1}\) 为 \(u\) 子树,有 \(x\) 个点是局部最小值,且 \(a_{fa_u}\) 比 \(u\) 小或大,\(a_u\) 的相对大小为 \(y\) 的方案数。
维护一个 \(g_{i,x,y,1/0}\) 表示考虑完前 \(i\) 个儿子,一共有 \(x\) 个局部最小值,相对大小为 \(y\) 且 \(u\) 是否比前面的儿子都小的方案数。
设当前儿子为 \(v\),则:
其中 \(siz\) 为前 \(i\) 个儿子子树大小和加 \(1\)。初始化 \(g_{0,0,1,1}=1\)。
再对 \(u\) 是否是局部最小值分类讨论:
- \(u\) 不是局部最小值。\(f_{u,x,y,1}\gets g_{|son_u|,x,y,0},f_{u,x,y,0}\gets g_{|son_u|,x,y,0/1}\)。
- \(u\) 是局部最小值。\(f_{u,x+1,y,1}\gets g_{|son_u|,x,y,1}\)。
特别的,当 \(u\) 是根时,有:
- \(ans_{x}\gets g_{|son_u|,x,y,0}\)。
- \(ans_{x+1}\gets g_{|son_u|,x,y,1}\)。
直接做时间复杂度 \(O(n^4)\)。
直接卷做到 \(O(n^3\log n)\)。
P10064 [SNOI2024] 公交线路
考虑判定一个集合 \(S\) 合不合法。
对于一个叶子 \(x\),记 \(T_x\) 为与 \(x\) 有边的点集合。则应该满足 \(\bigcap\limits_{x \text{ is leaf}}^{}T_x \not= \emptyset\)。
相当于形成一个连通块。点减边容斥,有:
- 对于一个点 \(u\)。如果对所有叶子 \(x\) 均满足:\(S\) 中存在同时经过 \(x,u\) 的路径 \(P\)。则贡献 \(1\)。
- 对于一条边 \((u,v)\)。如果对所有叶子 \(x\) 均满足:\(S\) 中存在同时经过 \(x,u,v\) 的路径 \(P\)。则贡献 \(-1\)。
答案即为所有贡献之和。
先做点的贡献。
路径两端都是叶子不太好做,考虑容斥。设 \(G(u,x)\) 为钦定 \(x\) 个叶子在 \(S\) 中不存在同时经过 \(x,u\) 的路径 \(P\) 的方案数。则合法方案数为 \(\sum\limits_{x}(-1)^xG(u,x)\)。
叶子被分进若干个子树和 \(u\) 子树外。钦定子树外的叶子一定经过 \(u\),对子树内的容斥。设 \(v_i\) 为 \(u\) 的第 \(i\) 个儿子,\(leaf_x\) 为 \(x\) 子树叶子数量,\(siz_x\) 为子树大小。定义状态函数 \(f_{i,j}\) 为考虑完前 \(i\) 个儿子子树,钦定 \(j\) 个叶子不经过 \(u\) 的方案数。有:
- \(f_{i,j+j'}\gets f_{i-1,j}\binom{leaf_{v_i}}{j} 2^{(\sum\limits_{k\le i}^{}siz_{v_{k}} - j)(siz_{v_i}-j)}\)。
那么 \(u\) 的贡献为 \(2^{\binom{n-siz_u}{2}+\sum\limits_{v\in son_u}^{}\binom{siz_v}{2}}\sum\limits_{x}^{}(-1)^x f_{|son_u|,x}2^{(siz_u-x)((n-siz_u)-(leaf-leaf_u))}(2^{siz_u-x}-1)^{leaf-leaf_u}\)。
时间复杂度 \(O(n^2)\)。
再做边的贡献。
枚举边 \((u,fa_u)\)。还是钦定子树内有 \(x\) 个点不经过这条边。
贡献为 \(-2^{\binom{siz_u}{2}+\binom{n-siz_u}{2}}\sum\limits_{x}(-1)^x \binom{leaf_u}{x}2^{(siz_u-x)((n-siz_u)-(leaf-leaf_u))}(2^{siz_u-x}-1)^{leaf-leaf_u}\)。
时间复杂度 \(O(n^2)\)。

浙公网安备 33010602011771号