[Luogu 3398] 仓鼠找sugar

<题目链接>


又是 LCA…

前两天死活写不过的一个题今天终于顺手切了。

思路嘛参考了一楼题解。

就是说,对于 a, b, c, d 四个点,

x = LCA(a, b), y = LCA(c, d),

两条路径有交叉,当且仅当 c, d 至少一个在 x 的子树下,且 a, b 至少一个在 y 的子树下。

由于我是 HLD 求的 LCA,第一遍 DFS 时顺手把子树大小求了,后边判断在不在一棵子属下的时候就可以很方便了。

就这样。

#include <algorithm>
#include <cstdio> const int MAXN = 100010; int n, q; struct Graph
{
struct Edge
{
int to;
Edge *next;
Edge(int to, Edge* next): to(to), next(next) {}
~Edge(void)
{
if(next != NULL)
delete next;
}
}*head[MAXN];
Graph(int n)
{
std :: fill(head + 1, head + n + 1, (Edge*)NULL);
}
~Graph(void)
{
for(int i = 1; i <= n; ++i)
delete head[i];
}
void AddEdges(int u, int v)
{
head[u] = new Edge(v, head[u]);
head[v] = new Edge(u, head[v]);
}
}*G; namespace HLD
{
int num;
struct Node
{
int depth, father, son, top, size, DFN;
}s[MAXN];
void DFS1(int u, int k)
{
s[u].depth = k;
s[u].size = 1;
int v;
for(Graph :: Edge *i = G -> head[u]; i != NULL; i = i -> next)
if(!s[v = i -> to].size)
{
DFS1(v, k + 1);
s[u].size += s[v].size;
s[v].father = u;
if(s[v].size > s[s[u].son].size)
s[u].son = v;
}
}
void DFS2(int u, int top)
{
s[u].top = top;
s[u].DFN = ++num;
if(s[u].son)
DFS2(s[u].son, top);
int v;
for(Graph :: Edge *i = G -> head[u]; i != NULL; i = i -> next)
if(!s[v = i -> to].DFN)
DFS2(v, v);
}
void Init(void)
{
DFS1(1, 1);
DFS2(1, 1);
}
int LCA(int x, int y)
{
int a, b;
while((a = s[x].top) ^ (b = s[y].top))
if(s[a].depth > s[b].depth)
x = s[a].father;
else
y = s[b].father;
return s[x].depth < s[y].depth ? x : y;
}
bool Range(int x, int y)
{
return s[x].DFN <= s[y].DFN && s[y].DFN < s[x].DFN + s[x].size;
}
bool Query(int a, int b, int c, int d)
{
int x = LCA(a, b), y = LCA(c, d);
return (Range(x, c) || Range(x, d)) && (Range(y, a) || Range(y, b));
}
} int main(void)
{
scanf("%d %d", &n, &q);
G = new Graph(n);
for(int i = 1, u, v; i < n; ++i)
{
scanf("%d %d", &u, &v);
G -> AddEdges(u, v);
}
HLD :: Init();
for(int i = 1, a, b, c, d; i <= q; ++i)
{
scanf("%d %d %d %d", &a, &b, &c, &d);
puts(HLD :: Query(a, b, c, d) ? "Y" : "N");
}
return 0;
}

谢谢阅读。

[Luogu 3398] 仓鼠找sugar的更多相关文章

  1. Luogu P3412 仓鼠找$sugar$ $II$

    Luogu P3412 仓鼠找\(sugar\) \(II\) 题目大意: 给定一棵\(n\)个点的树, 仓鼠每次移动都会等概率选择一个与当前点相邻的点,并移动到此点. 现在随机生成一个起点.一个终点 ...

  2. luogu P3412 仓鼠找sugar II 期望 树形dp

    LINK:仓鼠找sugar II 以前做过类似的期望题目 加上最后的树形dp不算太难 还是可以推出来的. 容易发现 当固定起点和终点的时候 可以先固定根 这样就不用分到底是正着走还是倒着走了. 1为根 ...

  3. luogu P3398 仓鼠找sugar [LCA]

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

  4. 【luogu P3398 仓鼠找sugar】 题解

    题目链接:https://www.luogu.org/problemnew/show/P3398 辣鸡树剖1300ms 倍增大法吼啊 #include <cstdio> #include ...

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

    题目:https://www.luogu.org/problemnew/show/P3398 原来只要把值记录成第几次就行了. 别忘了while(top[a]!=top[b])之后还要走一步. #in ...

  6. Luogu P3398 仓鼠找sugar

    这还是一道比较好的树剖题(去你的树剖,LCA即可) 这里主要讲两种思路,其实都是很基本也很经典的 1 树链剖分 还是先讲一下这种算法吧,虽然写起来很烦(不过感觉写多了就习惯了,而且还有一种莫名的快感) ...

  7. 洛谷 3398 仓鼠找sugar 【模板】判断树上两链有交

    [题解] 题意就是判断树上两条链是否有交.口诀是“判有交,此链有彼祖”.即其中一条链的端点的Lca在另一条链上. 我们设两条链的端点的Lca中深度较大的为L2,对L2与另一条链的两个端点分别求Lca, ...

  8. 【树链剖分/倍增模板】【洛谷】3398:仓鼠找sugar

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

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

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

随机推荐

  1. 【区间DP】codevs3657 括号序列题解

    题目描述 Description 我们用以下规则定义一个合法的括号序列: (1)空序列是合法的 (2)假如S是一个合法的序列,则 (S) 和[S]都是合法的 (3)假如A 和 B 都是合法的,那么AB ...

  2. Enterprise Library 6.0 参考源码索引

    http://www.projky.com/entlib/6.0/Diagnostics/Tracing/DiaLib.cs.htmlhttp://www.projky.com/entlib/6.0/ ...

  3. Android封装TitleBar基本适用所有常规开发

    Android封装TitleBar基本适用所有常规开发 github地址:https://github.com/SiberiaDante/SiberiaDanteLib/blob/master/sib ...

  4. 关于Jquery使用中遇到典型问题集锦

    ①$.post("url",{search:1},function(){},"json")请求数据成功就是不执行回调函数? 答:最大可能导致原因为 数据格式不正 ...

  5. 【硬件】- 英特尔CPU命名中的产品线后缀

    产品线后缀是CPU命名体系里最复杂最难懂的,在英特尔冗长的产品线中,CPU的后缀也是千变万化.不带后缀的CPU一般就是最普通的桌面级处理器,不管是性能还是价格都比较中庸,比如当前性价比较高的Core  ...

  6. [转帖]go的调度机制.

    调度器 主要基于三个基本对象上,G,M,P(定义在源码的src/runtime/runtime.h文件中) G代表一个goroutine对象,每次go调用的时候,都会创建一个G对象 M代表一个线程,每 ...

  7. 虚拟机centos 安装 redis 环境 linux 使用 java 远程连接 redis

    redis官网地址:http://www.redis.io/ 最新版本:2.8.3 在Linux下安装Redis非常简单,具体步骤如下(官网有说明): 1.下载源码,解压缩后编译源码. $ wget ...

  8. Linux使用技巧(一):vim中选中多行、复制和粘贴

    一.选中多行: 使用命令vim打开文件,移动光标至所选行的开头,按v进入视图,键盘上按向下键,选中所需行即可. 二.复制与粘贴 三种方法: 1)在上文第一部分的基础上,按y,然后移动光标至所需粘贴处, ...

  9. 安装配置openstack-dashboard(horizon)

    这里把dashboard安装在controller节点上. 1.安装程序包 # yum install -y openstack-dashboard 2.修改配置文件 # vim /etc/opens ...

  10. JS的类型和值

    1.类型 ECMAScript语言中所有的值都有一个对应的语言类型.ECMAScript语言类型包括Undefined.Null.Boolean.String.Number和Object. 对语言引擎 ...