一棵 n 点的树,你可以询问 dis(u,v)+dis(v,w)+dis(u,w)(u,v,w 两两不同)3n 次,询问两次 u 是否在 v 到 w 的路径上。求任意一条直径的两端点。
显然三个点的查询结果是三点间路径并的长度的两倍。
找直径,要求从一个点出发找最远点。
感知一下。固定一条链 (u,v) 向外询问 u,v,i,得到 i 到链的距离,显然链越短误差越小,于是先考虑在链上找一条边。
先得到链 (u,v) 上所有的点,即取到查询 u,v,i 最小值的 i。用一个 n。
一条歪路
随机选链上一个点 x,问出 u 到 x 的点,递归 u,x,期望两倍链长。实际上不必找支点。易知查询 u,i,j 的结果是 max(dis(u,i),dis(u,j))。只要找到链上离 u 最远的点,它与 v 就是一条边。若链上点的序列是 a,查询 u,a(i),a(i+1),找最大值的位置即可。用一倍链长。
接下来可以 n-链长 找到离边的最远点 ans1。只剩一个 n 能用了。
枚举直径另一端。如果相对红边处于异侧是容易的。
否则设图中的 a,b,c,询问得到 a+b+c,而 a+c,b+c 可以在问 ans1 时预处理。加加减减就得到 a+b 即两点间距离了。
总结:真 tm 怎么做都可以,赛时完全不发挥导致的。
https://qoj.ac/submission/860816 “找一条边”的算法可能有出入。
问题来了,“u 是否在 v 到 w 的路径上”干什么用的。
“固定一条链 (u,v) ”中,u,v 可能已经成边,u,v,i 查询结果最小为 4,此时当链 (u,v) 上“有”超过 2 个点时,(u,v) 为边,“有”1 个点时,得用一次。这也是本题比较卡人的一个特判。
n<=2 记得判,否则像我一样白花 40min。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?