传送门啦

思路:

那么从 $ A $ 到 $ B $ 可以分解成 先从 $ A $ 到 $ X $ 再从 $ X $ 到 $ B $ 。。。 另一个同理

假设能相遇 那么

要么在 $ A $ 到 $ X $ 的过程 $ A,B $ 相遇 要么在 $ X $ 到 $ B $ 的过程 $ A,B $ 相遇

对于在 $ A $ 到 $ X $ 的过程相遇的情况 又可以分解为:

情况1:

在 $ A $ 到 $ X $ 的过程和 $ C $ 到 $ Y $ 的过程 中 $ A,B $ 相遇

情况2:

在 $ A $ 到 $ X $ 的过程和 $ Y $ 到 $ D $ 的过程 中 $ A,B $ 相遇

呃呃呃。。。

相遇的情况 :

$ a->X , c->Y $ 相遇(可以认为 松鼠和他基友都在网上冲)

$ a->X,Y->d $ 相遇(一个往上冲,一个在往下冲)

$ X->b,c->Y $ 相遇(一个往下冲 一个往上冲)

$ X->b,Y->d $ 相遇(都往下冲)

根据树中的每一个节点的父亲都是唯一的, $ lca $ 可以认为是他们最短路径上深度最浅的那个点, $ a,b,c,d $ 到他们 $ lca $ 的路径是唯一的。

而上述的 $ 4 $ 个 $ lca $ 中深度最大的那一个 我们姑且记为 $ S $ ,那么 $ S $ 一定是 $ a,b $ 中的一个和 $ c,d $ 的一个的 $ lca $ (我们假设是 $ lca(a,d) $ )

那么如果 $ S $ 的深度大于 $ x,y $ 中较大的的那一个,说明 $ a $ 在和 $ d $ 在往上冲的过程中一定要经过他们的 $ lca $ ,也就是 $ S $ ,再经过 $ x $ 或者是 $ y $ 。因为 $ a $ 和 $ d $ 是 $ a,b $ 中的一个和 $ c,d $ 中的一个,他们还要冲向 $ X $ 或者是 $ Y $ 。这种情况必然相遇;

在 $ X 、Y $ 中取一个最大,再在 $ lca(a,c).lca(a,d),lca(b,c),lca(b,d) $ 这四个当中取一个最大,如果后者的深度大于等于前者,那么可以相遇,否则不能;

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #define re register
  7. using namespace std ;
  8. const int maxn = 5 * 1e5 + 4 ;
  9. inline int read () {
  10. int f = 1 , x = 0 ;
  11. char ch = getchar () ;
  12. while (ch > '9' || ch < '0') {if(ch == '-') f = -1 ; ch = getchar () ;}
  13. while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0' ; ch = getchar () ;}
  14. return x * f ;
  15. }
  16. int n , q , u , v , a , b , c , d ;
  17. int head[maxn] , tot ;
  18. struct Edge {
  19. int from , to , next ;
  20. }edge[maxn << 1] ;
  21. inline void add (int u , int v) {
  22. edge[++tot].from = u ;
  23. edge[tot].to = v ;
  24. edge[tot].next = head[u] ;
  25. head[u] = tot ;
  26. }
  27. int dep[maxn] , f[maxn][21] ;
  28. inline void dfs (int x , int fa) {
  29. dep[x] = dep[fa] + 1 ;
  30. f[x][0] = fa ;
  31. for(re int i = 1 ; (1 << i) <= dep[x] ; ++ i) {
  32. f[x][i] = f[f[x][i - 1]][i - 1] ;
  33. }
  34. for(re int i = head[x] ; i ; i = edge[i].next) {
  35. int v = edge[i].to ;
  36. if(v != fa) dfs(v , x) ;
  37. }
  38. }
  39. inline int lca (int a , int b) {
  40. if(dep[a] < dep[b]) swap(a , b) ;
  41. for(re int i = 18 ; i >= 0 ; -- i) {
  42. if((1 << i) <= (dep[a] - dep[b])) {
  43. a = f[a][i] ;
  44. }
  45. }
  46. if(a == b) return a ;
  47. for(re int i = 18 ; i >= 0 ; -- i) {
  48. if((1 << i) <= dep[a] && f[a][i] != f[b][i]) {
  49. a = f[a][i] ;
  50. b = f[b][i] ;
  51. }
  52. }
  53. return f[a][0] ;
  54. }
  55. int main () {
  56. n = read () ; q = read () ;
  57. for(re int i = 1 ; i <= n - 1 ; ++ i) {
  58. u = read () ; v = read () ;
  59. add(u , v) ;
  60. add(v , u) ;
  61. }
  62. dfs(1 , 1) ;
  63. for(re int i = 1 ; i <= q ; ++ i) {
  64. a = read () ; b = read () ; c = read () ; d = read () ;
  65. int fm1 = max(dep[lca(a , b)] , dep[lca(c , d)]) ;
  66. int fm2 = max(max(dep[lca(a , c)] , dep[lca(a , d)]) , max(dep[lca(b , c)] , dep[lca(b , d)])) ;
  67. if(fm2 >= fm1)
  68. printf("Y\n");
  69. else
  70. printf("N\n");
  71. }
  72. return 0 ;
  73. }

洛谷P3398 仓鼠找suger的更多相关文章

  1. 洛谷p3398仓鼠找suger题解

    我现在爱死树链剖分了 题目 具体分析的话在洛谷blog里 这里只是想放一下改完之后的代码 多了一个son数组少了一个for 少了找size最大的儿子的for #include <cstdio&g ...

  2. 洛谷 P3398 仓鼠找sugar 解题报告

    P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...

  3. 洛谷P3398 仓鼠找sugar [LCA]

    题目传送门 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...

  4. 洛谷P3398 仓鼠找sugar

    题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...

  5. 洛谷 P3398 仓鼠找sugar —— 树链剖分

    题目:https://www.luogu.org/problemnew/show/P3398 树链剖分一下,路径就变成线段树上的几个区间: 两条路径相交就是线段树上有区间相交,所以在相应位置打个标记, ...

  6. 洛谷——P3398 仓鼠找sugar

    https://www.luogu.org/problem/show?pid=3398#sub 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴 ...

  7. 洛谷 P3398 仓鼠找sugar 题解

    每日一题 day44 打卡 Analysis 首先有一个结论:先找 p1=(a,b),p2=(c,d) 的LCA的深度,在与(a,c),(a,d),(b,c),(b,d)中最深的LCA n的深度比较, ...

  8. 洛谷 [P3398] 仓鼠找sugar

    树剖求LCA 我们可以发现,两条路径ab,cd相交,当且仅当 dep[lca(a,b)]>=dep[lca(c,d)]&(lca(lca(a,b),c)==lca(a,b)||lca(l ...

  9. 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)

    洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...

随机推荐

  1. 【学习总结】GirlsInAI ML-diary 总

    2019-1-7 GirlsInAI第一期: 人工智障工程师养成计划,代号ML-diary 原博github链接:Girls-In-AI 环境:Windows / MacOS 工具:Anaconda ...

  2. ABP新增模块可能遇到的问题

    当我们新增一个模块时: public class SSORedisModule: AbpModule { //public override void PreInitialize() //{ // b ...

  3. iOS 利用高德地图WMS服务

    Demo:  https://github.com/xushiyou23/AMapTesting 转: 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net ...

  4. python之装饰器初识

    一.@abstractmethod 1.抽象类的作用:规范编程模式 多人开发.复杂的需求.后期的扩展 是一种用来帮助我们完成规范化的手段 2.如何定义抽象类 1,from abc import ABC ...

  5. eclipse安装Activiti

    一. eclipse自己下载 打开eclipse软件,然后点击菜单栏的help选项,选择install New Software,示例如下: 出现如下对话框: 点击添加[Add]按钮,出现如下对话框 ...

  6. mpvue——引入vant_weapp组件

    克隆仓库 克隆后,将dist目录下的所有文件复制到项目中的/static/vant/目录下,vant目录是我自己创建为了区分的 git clone https://github.com/youzan/ ...

  7. mpvue——页面跳转

    两个页面 两个页面的跳转,只是单纯的A->B这种跳转. 组件 直接使用小程序的组件,navigator,里面还有一些其他的参数,大家可以自行翻阅官方文档 <navigator url=&q ...

  8. [模板]快速傅里叶变换(FFT)

    Miskcoo大佬的多项式全家桶传送门 rvalue大佬的FFT讲解传送门 用途 将多项式快速(nlogn)变成点值表达,或将点值表达快速变回系数表达(逆变换),(多数时候)来达到求卷积的目的 做法 ...

  9. 这可能是最为详细的Docker入门吐血总结

    这可能是最为详细的Docker入门吐血总结  https://www.cnblogs.com/ECJTUACM-873284962/p/9789130.html Docker是什么? 在计算机技术日新 ...

  10. os.listdir()、os.walk()和os.mkdir()的用法

    内容主要参照博客https://blog.csdn.net/xxn_723911/article/details/78795033 http://www.runoob.com/python/os-wa ...