2 条题解
-
1
本题就相当于找 lca。
方法一:像树剖找 lca 一样,让深度最大的点(其实就是值更大的点)往上跳一步(
u = u / 2
),最后跳到 lca 的位置时跳的步数就是两点之间的边数。while(n != m) { if(n < m) swap(n, m); n /= 2, ans++; } return printf("%lld\n", ans);
方法二:先假定 lca ,然后每次判断两个点是不是在 lca 的同一侧,如果否那么现在的lca就是真正的 lca;否则我们把 lca 设为两个点那一侧的儿子,同时答案 ,然后继续计算,直到两个点不同侧或一个点成为 lca。
代码又臭又长,就不贴了。
注意判断两个点是否在同一侧时令
fn = n * 2 - ln + 1
(ln
为 lca 的子树内n
所在层的节点个数,即如果n
超过了其一半说明n
在右侧;m
同理),如果fn * fm < 0
说明两个点不在同一侧。注意如果直接乘可能会爆 long long,我们应该先把fn
换成sgn(fn)
; 记得特判lca = n
的情况。说句闲话,这题解怎么还可以自己赞/踩自己呢
- 1
信息
- ID
- 3
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 35
- 已通过
- 11
- 上传者