杂题选做 9

【MX-S9-T3】「LAOI-16」天外来物

可以想到,我们为每一种不同的虚树找一个代表元出来,仅计算代表元的贡献即可。

分析可以构建出这种虚树的最小区间是什么。发现如果我们扔掉一个在内部的点,虚树的形态是避讳变化的,因为存在另外的两点经过该点;否则该点是一个叶子,扔掉该点会使得虚树也少一个叶子。

于是我们可以找到那些左右端点均是叶子的区间,仅计算这些区间的贡献即可。

\(L_i\) 表示最大的 \(j\) 使得在 \([i,j]\) 构成的虚树上 \(i\) 是叶子,\(R_i\) 同理。于是我们需要计算 \(r \le R_l\)\(l \ge L_r\)\([l,r]\) 数量。考虑对左端点从 \(n\)\(1\) 扫描线,使用线段树维护所有满足 \(l \ge L_r\)\(r\),即扫到 \(r\) 时加入,扫到 \(L_r-1\) 时删除,然后对所有在 \([l,R_l]\) 内已加入的点的答案 \(+1\),查询求区间和即可。

现在还剩一个问题:如何求 \(L_i,R_i\)。对于 \(L_i\),考虑什么时候存在两个点经过该点,这其实就是删掉这个点后构成的若干连通块中最小编号的次小值,拍到 dfn 上使用线段树维护即可。\(R_i\) 是类似的。

时间复杂度为 \(O(n \log n)\),可以通过。

Path Choosing

待补。

[EGOI 2025] Laser Strike / 激光突击

显然 1 bit 只能告诉第二个人第一次删什么点。那么我们能传的信息几乎都集中于删除的顺序了。

考察菊花,发现只需要每次删除上一次没有出现的点即可;考察链,只需要每次删除上一次出现了的点……但这不是和我们在菊花的策略重合了吗?

调整删除顺序,既然我们不想让删除的点与上一次有重合,那么我们就在两个端点交替取即可。对于第二轮以后删掉的边,我们可以删除在之前出现过的那个点,但是我们怎么知道第一轮取的第二次删除的是哪个点呢?

再次考虑删除顺序的问题。我们可以比较两条边的字典序,若第二次删除的边小于第一次则删编号较小的那个,否则删编号较大的那个。于是链得到了解决,且该策略可以与菊花结合,很好地套用在一般树上。

具体地,我们对每个所有儿子均是叶子的节点随意找出一个儿子,这是我们最初要删掉的点。一旦这些点被删除,我们就可以通过下面两条规则让第二个人快速识别应该删哪个点:

  • 若删除的边与上一条边有公共点,删除不是公共点的那个点(同菊花)。

  • 否则,删除最近一次出现最晚的那个点(同链)。

对于我们最初要删除的点,考虑拓展在链的第一轮区分的方法:将所有边按照字典序排序,在每个极长同类型边内部 reverse,这样第二个人就可以在每次遇到上一条边字典序比它小的情况下正确切换类型。

最后一个问题,正确应用规则 2 需要满足与上一条边无公共点,因此需要保证除根外每层至少有两个点。以直径重点为根(若点数为偶数则中间两个点均为根)即可。

[ICPC 2025 Xi'an R] Directed Acyclic Graph

发现我们需要构造较多的合法集合,于是考虑能不能造出一些独立控制某些点是否在 \(f(S)\) 中的结构,达到能使得答案集合数量指数增长的效果。

想让某个点 \(u\) 不出现在 \(f(S)\) 中,只要让 \(S\) 中的某个点不可达 \(u\) 就好了。由于我们的目标是独立控制该点,因此我们也需要让该点能到达其余的点。不难想到将点分为两组 \(a_1 \sim a_t\)\(b_1 \sim b_t\)\(a_i\) 可以到达除了 \(b_i\) 以外的所有第二组点,这样在 \(S\) 中加入 \(a_i\) 等价于不让 \(b_i\)\(f(S)\) 中出现,否则 \(b_i\) 会在 \(f(S)\) 中出现,通过前后缀优化建图可以将边数降到 \(n+6t\) 左右。大致结构如下:

但是这也太垃圾了。为什么呢?

你发现,由于 \(m-n\) 太小,所用来建造控制结构的边数会很少,但是 \(n\) 很大,因此有大量的节点都被我们浪费掉了。考虑扩充一下两排的节点,使得每一个单独的控制结构可以产生更多种类的集合。

假设我们把上述构造的每一个点扩充到一组 \(d\) 个点,那么我们的目标是,可以通过选取组内不同的点,构造出不同的可达性。首先不选 \(a_i\) 组内任何一个点跟上面一样,是让所有 \(b_i\) 组内的点都加入 \(f(S)\);假设我们选了 \(a_{i,1}\),我们希望在 \(f(S)\) 中扣掉 \(b_{i,1}\),那么不妨让 \(b_{i,j}\) 连向 \(b_{i,j+1}\),然后让 \(a_{i,1}\) 连向 \(b_{i,2}\),这样 \(b_{i,1}\) 就被排除在外了。对于其余的 \(a_{i,j}\) 也是同理的,连向 \(b_{i,j+1}\) 即可。

除此以外,为了保证 \(a_{i,j}\) 可达所有 \(k \neq i\)\(b_k\) 组,还要让所有 \(a_{i,j}\) 连向 \(a_{i,j+1}\),并让所有 \(a_{i,d}\)\(b_{i,1}\) 像原来的构造一样接入一个前后缀优化建图。大致结构如下(未画出后缀优化建图):

实际实现的时候可以优化掉边上的一些点和边,最终所用边数为 \(n+t(d+2)-7\),所用点数 \((2d+2)t-1\),取 \(d=3,t=7\) 时,边数恰好为 \(128\),能构造出 \((d+1)^t=16384\) 种集合,可以通过。

[PKUWC 2025] 网友小 Z 的树

找出直径,可以考虑增量构造。

假设我们找出了前 \(i-1\) 个点的直径 \((x,y)\) 并维护了 \(\text{dis}(x,y)\),需要加入一个点 \(u\),我们希望得知 \(\text{dis}(u,x)\)\(\text{dis}(u,y)\)。但你发现我们只有一个方程,却需要解出两个未知数,这是不可能的。考虑多任意维护一个点 \(z\) 与距离 \(\text{dis}(x,z)\)\(\text{dis}(y,z)\),我们就能以 \(3\) 次询问的代价解出 \(\text{dis}(u,x)\)\(\text{dis(u,y)}\)\(\text{dis}(u,z)\)。具体地,设 \(A=\text{dis}(u,x)+\text{dis}(u,y)+\text{dis}(x,y),B=\text{dis}(u,y)+\text{dis}(u,z)+\text{dis}(y,z),C=\text{dis}(u,x)+\text{dis}(u,z)+\text{dis}(x,z)\),那么有:

\[\text{dis}(u,x)=\dfrac{A-B+C-\text{dis}(x,z)-\text{dis}(x,z)+\text{dis}(y,z)}{2} \]

\[\text{dis}(u,y)=\dfrac{A+B-C-\text{dis}(x,z)+\text{dis}(x,z)-\text{dis}(y,z)}{2} \]

\[\text{dis}(u,z)=\dfrac{B+C-A+\text{dis}(x,z)-\text{dis}(x,z)-\text{dis}(y,z)}{2} \]

于是这题就被解决了……吗?我们如何得知最初的 \(x,y,z\) 呢?

那么我们就需要找出一个初始态,使得我们可以直接得知前若干个点的两两距离。沿用解方程的方法,我们发现 \(n=5\) 时有 \(10\) 对点对以及 \(10\) 组方程,可以使用高斯消元直接计算出距离。

于是再特判 \(n \le 4\) 即可,询问次数为 \(10+3(n-5)=3n-5\)

[集训队互测 2025] 少年汹涌

题目本质要求我们求所有点 \(a_i\) 以及根节点在 \(i \to i+w_{\text{popcnt}(i)}\) 这棵树上的虚树大小。

首先来考虑一下 \(n=1\) 应该如何解决。可以想到尝试使用倍增状物,每次跳 \(2^k\) 步,但是问题在于我们没有办法快速地维护 \(\text{popcnt}\) 的变化。观察到 \(w_i \le 62\),因此我们考虑将一个数拆分为 \(64p+q\) 的形式。那么每跳一次,\(p\) 的变化量至多为 \(1\),看起来好维护了很多。

具体地,考虑令 \(p\) 增加 \(2^k\) 会对 \(\text{popcnt}\) 带来什么样的影响。对于 \(p\) 的最高位 \(>k\) 的情况,这是好刻画的:显然只会让 \(\text{popcnt}\) 加一。对于 \(p\) 的最高位恰好为 \(k\)\(\text{popcnt}\) 会保持不变。其余情况较难刻画,不妨直接加入一条限制,令 \(f_{i,j,k}\) 表示当前 \(\text{popcnt}=i\)\(q=j\),且当前数的 \(p\)\(2^k\) 倍数时,令 \(p\) 增加 \(2^k\) 后的 \(q\) 值是多少,以及同样的 \(g_{i,j,k}\) 表示所需的步数。

这样我们就可以解决 \(n=1\) 的部分了:不断令 \(p\) 增加可以增加的最大的 \(2^k\),整个过程可以分为两个阶段:

  • 每次跳的 \(k\) 等于 \(p\)\(\text{lowbit}\)

  • 每次跳的 \(k\) 小于 \(p\)\(\text{lowbit}\)

第一阶段,我们只需要不断检查跳 \(\text{lowbit}\) 会不会超即可;第二阶段倒序遍历所有 \(2^k\),同样判断能否跳即可。最后可能还有若干次 \(q\) 的变动,暴力即可。

现在考虑扩展到 \(n>1\)。自然的想法是,我们每次加入一个 \(a_i\),找到其第一次碰到已被经过的数,并加入这一段路径的长度。在 \(n=2\) 时就是 \(\text{lca}\),于是我们先想想怎么求出两个数的 \(\text{lca}\)

类比树上倍增 \(\text{lca}\),假设两个数为 \(x,y\),先让 \(x\) 跳到 \(p_x=p_y\),此时若 \(x>y\) 再交换一下即可。剩下的部分跟求一个点深度几乎没有区别,加一个不能让两个数的下一步数相同的限制即可。

多个数的情况,加入一个 \(a_i\) 时第一个碰到的已经过的数就是 \(\min\limits_{j<i} \text{lca}(a_i,a_j)\)。但是暴力计算时间复杂度会达到 \(O(n^2 \log V)\),无法接受。但是我们发现,在之前跳 \(\text{lca}\) 的第一步中,我们让 \(x\) 不断跳到最大的 \(<y\) 的数,此时一定是有 \(y-x \le 63\) 的!这就意味着,如果我们维护所有 \(<a_i\) 的链,这些链头至多只有 \(63\) 种。

那么我们只需要将 \(a_i\) 排序,从小到大处理,并维护一个去重后的所有 \(j<i\)\(a_j\) 跳到不超过 \(a_i\) 的最大数即可。时间复杂度是 \(O(n \log^2 V + \log^3 V)\)

[PA 2020] Ogromne drzewo

待补。

Cyclic Hamming (Hard Version)

待补。

Rounddog

待补。

[CTT 2025] 三选二

待补。

[PA 2020] Trzy drogi

待补。

[AGC027 D] Magician

待补。

posted @ 2026-08-03 16:42  luqyou  阅读(17)  评论(0)    收藏  举报