1 条题解
-
0
1. 核心算法概览
本题包含两个子问题:
- 查询 1 (
1 x y):求 到 路径上的本质不同颜色数。这是经典的 树上莫队 问题。 - 查询 2 (
2 A B):求从 路径上任选点 ,从 路径上任选点 ,路径 颜色数的期望。- 期望 总方案数 所有组合的颜色数之和。
- 这是一个高维统计问题,可以通过 差分 和 贡献法 转化为区间历史和问题,结合莫队算法维护。
2. 解题思路详解
子问题 1:路径颜色数(树上莫队)
对于树上路径查询,通常使用欧拉序(Euler Tour)或者 DFS 序将树上路径转化为线性区间。 这份代码采用的是 DFS 序 + 差分 的方式(虽然莫队通常处理欧拉序,但这里结合了
vis数组进行节点的显隐操作,即 XOR 莫队 的思想)。- 区间转化:
- 对于路径 (设 ),如果是直链( 是 的祖先),对应区间 。
- 如果不是直链,对应区间 ,但需要额外处理 。
- 状态维护:
- 使用
cnt[color]记录当前区间内颜色的出现次数。 - 使用
vis[node]记录节点是否在当前区间内(处理路径时,出现两次的节点会抵消,代表不在路径上)。 - 变量
res维护当前的本质不同颜色数量。
- 使用
子问题 2:期望/总和查询(贡献法 + 链表维护)
这是本题的难点。要求 $\sum_{x \in Path(1, A)} \sum_{y \in Path(1, B)} \text{CountDistinct}(Path(x, y))$。
直接做非常困难,代码中利用了差分思想:
- 预处理 :表示 这条链上所有点对的颜色数贡献(代码中
dfsp函数)。 - 利用 LCA 性质,将 和 的询问拆解为若干个关键点区间的询问。
- 代码中
ans[i] = f[u] + f[v] - dep[lc]是基础差分。 - 后续加入的
qr[++m]是为了处理交叉部分的贡献,将树上的矩形区域查询转化为了莫队能够处理的线性区间查询。
- 代码中
贡献法的计算公式: 对于一个颜色 ,它在当前区间(对应树上一条路径或点集)内的贡献等于:
为了在 时间内维护“不包含颜色 的子路径数”,代码在莫队移动指针时维护了一个 双向链表:
- 链表结构:
pr[x],nx[x]记录当前区间内,节点 在某种顺序下的前驱和后继(同色节点)。 - 距离计算:
st.dis(p, r)计算树上距离。 - 变量含义:
ds: 当前区间内的节点总数。sd: 当前所有颜色内部相邻节点距离产生的“无效子路径”贡献和。sl1, sl2: 维护左端点相关的距离一次项和二次项(用于快速计算加入左端点时的贡献)。sr1, sr2: 维护右端点相关的距离一次项和二次项。
代码中的
query(2)函数就是利用这些变量,通过公式算出当前的贡献总和:ll ans = 1ll * ds * (ds + 1) / 2 * res - sd; // 总可能 - 内部间隔造成的无效 ans -= (sl2 + sl1) / 2; // 减去左边界造成的无效 ans -= (sr2 + sr1) / 2; // 减去右边界造成的无效3. 代码结构分析
-
输入与预处理:
- IO 优化:
namespace IO处理了快读快写,因为数据量较大()。 - 随机生成:题目为了减小输入文件大小,使用了 LCG 生成器生成树边和颜色。
- ST 表 (
ST_table):用于 查询 LCA 和 查询树上两点距离dis(u, v)。同时实现了find(x, y)寻找 在 方向上的儿子(Level Ancestor)。
- IO 优化:
-
莫队核心 (
insL,insR,delL,delR):- 这四个函数非常关键,它们不仅维护
cnt和res(用于查询 1),还维护了链表和sd, sl, sr等变量(用于查询 2)。 - 例如
insL(p):在左侧插入节点 。- 如果 的颜色是第一次出现,更新
fir(首位)、las(末位),并更新边界贡献sr2, sr1等。 - 如果不是第一次,找到当前该颜色的首位
fir,建立链接,计算 和fir之间的距离d,从sl(左边界贡献)中扣除这部分,并加入到sd(内部贡献)中。
- 如果 的颜色是第一次出现,更新
- 这四个函数非常关键,它们不仅维护
-
主处理流程:
- 先 DFS 建立 ST 表。
dfsp预处理 。- 处理询问:
- 类型 1:直接加入莫队查询队列。
- 类型 2:拆分为差分项和莫队查询项。这里使用了复杂的差分拆解,将 拆成了 及其儿子相关的多个查询。
- 莫队排序:使用奇偶性优化(Hilbert 曲线或者块内奇偶排序)来最小化指针移动距离。
B = tim / sqrt(m + 1) + 1计算块大小。 - 莫队执行:
curL,curR移动时调用updL,updR。upd函数中利用vis数组做 XOR 操作(存在则删,不存在则加),这是处理树上路径莫队的标准技巧。
4. 复杂度
- 时间复杂度:。莫队算法的标准复杂度。由于操作较多(链表维护、距离计算),常数较大,但 ST 表求距离是 的,保证了效率。
- 空间复杂度:。
5. 总结
这道题是数据结构综合应用的典范:
- 问题转化:利用差分将高维期望问题转化为区间和问题。
- 算法选择:树上莫队处理离线区间查询。
- 数据结构:动态维护链表和统计变量来支持 的贡献计算。
代码中使用
basic_string代替vector以优化内存和速度,手写 IO,以及 ST 表求 LCA,都是为了在 10s 的时限内通过 级别的数据(考虑到莫队的根号复杂度和大常数)。 - 查询 1 (
- 1
信息
- ID
- 6140
- 时间
- 7000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者