1 条题解
-
0
「雅礼集训 2018 Day10」文明 题解
问题重述
给定一棵 个节点的树,进行 次游戏。每次游戏有 个玩家,初始位置分别为 (黈力是 号玩家,初始位置为 )。玩家轮流操作,每轮操作将自己的领土向外扩展 的距离(占领所有相邻的未占领节点)。问黈力最终能占领多少个节点。
问题转化
通过分析游戏过程,可以得出以下关键性质:
-
扩展速度:所有玩家每轮都以相同速度(距离 )扩展
-
竞争规则:节点 最终被玩家 占领当且仅当:
- (距离最小)
- 在距离相同的玩家中,编号最小的获胜(黈力是 号,有优先级)
-
最终状态:每个节点属于离它最近的初始点,距离相同时属于编号最小的玩家
因此,问题转化为:在树上为每个节点分配离它最近的"首都" ,距离相同时选择编号小的,统计黈力()占领的节点数。
算法思路
核心观察
设黈力的初始点为 (代码中的变量名),其他玩家的初始点为 。对于任意节点 :
- 如果 到 的距离 到其他所有 中点的距离,则 属于黈力
- 否则属于其他玩家
这等价于:黈力占领的区域是以 为中心的"Voronoi 区域",边界由到 和到其他点距离相等的点构成。
关键引理
对于两个点 和 ,它们的势力范围分界点 定义为:
- 如果 ,则分界点在连接路径的中点
- 更一般地, 是使得 的点
重要性质: 到 和 的距离差为 (取整处理)。
算法步骤
1. 预处理
- 使用树链剖分或倍增法预处理 LCA,支持 查询任意两点距离
- 计算每个节点的 DFS 序、子树大小、重链等信息
2. 对于每次查询
- 输入 个点, 是黈力的首都
- 对于每个其他玩家的点 :
- 计算 : 和 的势力分界点
- 在 DFS 序中标记 的子树(这些节点离 更近)
3. 势力范围计算
设 为所有分界点的 DFS 序集合(包括 自身)。
情况 1:没有祖先关系的点
- 按 DFS 序排序,贪心计算被其他玩家占领的子树
- 如果某个分界点的子树完全在当前已覆盖区间外,则整个子树被其他玩家占领
- 从答案 中减去这些子树的大小
情况 2:存在分界点是 的祖先
- 设 是 的最近祖先分界点
- 的子树中,只有深度 的部分可能属于黈力
- 需要特殊处理 的父节点方向的部分
核心函数解析
Find(u)函数计算 和 的势力分界点:
inline int Find(int u) { int lca = LCA(rt, u); int dist = dep[u] + dep[rt] - 2 * dep[lca]; int k = (dist - 1) / 2; // 距离除以2下取整 if (k <= dep[u] - dep[lca]) return Anc(u, k); // 在u到lca的路径上 else return Anc(rt, dist - k); // 在rt到lca的路径上 }势力范围计算逻辑
- 收集所有分界点:对于每个其他玩家点 ,计算 并加入集合
- 按 DFS 序处理:
- 如果分界点 的 DFS 序区间 与已覆盖区间不重叠
- 则该整个子树被其他玩家占领
- 处理祖先关系:
- 如果存在分界点是 的祖先
- 需要减去 的父节点方向的节点(这些节点离祖先更近)
时间复杂度分析
- 预处理:
- 每次查询:
- 计算 个分界点:
- 集合操作:
- 总复杂度:
- 总复杂度:$O(n \log n + \sum k_i \log n) \leq O(n \log n + 10^6 \log n)$,可以通过
代码实现要点
- 树链剖分:用于快速求 LCA 和树上距离
- 倍增法:
Anc(u, x)函数用于求 的 级祖先 - DFS 序性质:子树在 DFS 序中是连续区间
- 集合维护:使用
std::set维护分界点的 DFS 序
正确性证明
关键引理证明
对于任意节点 :
- 如果 在 的子树中且不在更近的其他分界点子树中,则
- 因此 被玩家 占领
- 反之,如果 不在任何分界点的子树中,则 对所有 成立
贪心正确性
按 DFS 序处理时,由于子树区间是连续的,且区间要么包含要么不相交,可以使用贪心选择:
- 如果当前区间起点大于已覆盖区间的终点,说明这是一个新的不相交子树
- 该子树全部被其他玩家占领
样例验证
以题目样例第一组数据为例:
- ,,,
- 计算 :,,返回
- 分界点集合:
- 的子树大小为 (节点 )
- 但这些节点中, 离 更近, 离 比离 更近
- 黈力占领节点:,共 个
总结
本题通过将游戏过程转化为树上最近邻分类问题,利用树链剖分和 DFS 序的性质,高效计算黈力的势力范围。核心在于理解势力分界点的计算和处理祖先关系的特殊情况。算法时间复杂度优秀,能够处理 , 的大规模数据。
-
- 1
信息
- ID
- 6053
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者