传送门啦

思路:

那么从 $ 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) $ 这四个当中取一个最大,如果后者的深度大于等于前者,那么可以相遇,否则不能;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define re register
using namespace std ;
const int maxn = 5 * 1e5 + 4 ; inline int read () {
int f = 1 , x = 0 ;
char ch = getchar () ;
while (ch > '9' || ch < '0') {if(ch == '-') f = -1 ; ch = getchar () ;}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0' ; ch = getchar () ;}
return x * f ;
} int n , q , u , v , a , b , c , d ;
int head[maxn] , tot ; struct Edge {
int from , to , next ;
}edge[maxn << 1] ; inline void add (int u , int v) {
edge[++tot].from = u ;
edge[tot].to = v ;
edge[tot].next = head[u] ;
head[u] = tot ;
} int dep[maxn] , f[maxn][21] ; inline void dfs (int x , int fa) {
dep[x] = dep[fa] + 1 ;
f[x][0] = fa ;
for(re int i = 1 ; (1 << i) <= dep[x] ; ++ i) {
f[x][i] = f[f[x][i - 1]][i - 1] ;
}
for(re int i = head[x] ; i ; i = edge[i].next) {
int v = edge[i].to ;
if(v != fa) dfs(v , x) ;
}
} inline int lca (int a , int b) {
if(dep[a] < dep[b]) swap(a , b) ;
for(re int i = 18 ; i >= 0 ; -- i) {
if((1 << i) <= (dep[a] - dep[b])) {
a = f[a][i] ;
}
}
if(a == b) return a ;
for(re int i = 18 ; i >= 0 ; -- i) {
if((1 << i) <= dep[a] && f[a][i] != f[b][i]) {
a = f[a][i] ;
b = f[b][i] ;
}
}
return f[a][0] ;
} int main () {
n = read () ; q = read () ;
for(re int i = 1 ; i <= n - 1 ; ++ i) {
u = read () ; v = read () ;
add(u , v) ;
add(v , u) ;
}
dfs(1 , 1) ;
for(re int i = 1 ; i <= q ; ++ i) {
a = read () ; b = read () ; c = read () ; d = read () ;
int fm1 = max(dep[lca(a , b)] , dep[lca(c , d)]) ;
int fm2 = max(max(dep[lca(a , c)] , dep[lca(a , d)]) , max(dep[lca(b , c)] , dep[lca(b , d)])) ;
if(fm2 >= fm1)
printf("Y\n");
else
printf("N\n");
}
return 0 ;
}

洛谷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. Nginx部署静态页

    简答说一下如何用Nginx部署静态网页,并绑定域名访问 1.通过FTP上传静态页到服务器指定目录 2.编写nginx的.conf文件 3.重启nginx 如图,这是centos上传文件路径 nginx ...

  2. openstack搭建之-创建实例(13)

    一. 创建flat网络的实例 #运行admin环境变量,创建网络类型为flat . admin-openrc openstack network create --share \ --provider ...

  3. python基础概念(转)

    基础回顾: 1.集合 集合有2个重要作用:关系测试(并集,差集,交集)和去重. 2.文件编码 2.7上默认文件编码是ASCII码,因为不支持中文,就出了GB2312,在2.7上要支持中文就必须申明文件 ...

  4. Flutter之List

    void listDemo() { // 1.list的创建 listCreate(); // 2.多种类型的输出 listPrint(); // 3.添加数据 listAddElement(); / ...

  5. 【转】深入分析 Parquet 列式存储格式

    Parquet 是面向分析型业务的列式存储格式,由 Twitter 和 Cloudera 合作开发,2015 年 5 月从 Apache 的孵化器里毕业成为 Apache 顶级项目,最新的版本是 1. ...

  6. 不用Ajax时的传参方法

    不用Ajax时的怎么传参 创建一个form表单 function test(){ var params = { "参数名": "参数值" }; postExce ...

  7. rest framework 序列化

    serializers 序列化组件 可以实现很轻松的互相转换,最常用的组件 ,用量最大的组件 源码位置 rest_framework.serializers 源码中需要用到的    rest_fram ...

  8. Forget Guava: 5 Google Libraries Java Developers Should Know

    Forget Guava: 5 Google Libraries Java Developers Should Know Published on 2016 7 13 Somenath PandaFo ...

  9. Docker容器进入的4种方式

    Docker容器进入的4种方式 $ sudo docker ps $ sudo docker exec -it 775c7c9ee1e1 /bin/bash 在使用Docker创建了容器之后,大家比较 ...

  10. (转)Java8内存模型—永久代(PermGen)和元空间(Metaspace)

    背景:介绍java8中永久代到元空间的转变. Java8内存模型—永久代(PermGen)和元空间(Metaspace) 一.JVM 内存模型 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法 ...