P3379 【模板】最近公共祖先(LCA)(LCT)
\(\color{#0066ff}{ 题目描述 }\)
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
\(\color{#0066ff}{输入格式}\)
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
\(\color{#0066ff}{输出格式}\)
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
\(\color{#0066ff}{输入样例}\)
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
\(\color{#0066ff}{输出样例}\)
4
4
1
4
4
\(\color{#0066ff}{数据范围与提示}\)
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
\(\color{#0066ff}{ 题解 }\)
拿LCT只为了求个LCA
有毒啊
access的时候记录一下上一个点(下一个链尾)
access第二个点的时候,最后一次的那个链的接触点就是LCA
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL in() {
char ch; int x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 5e5 + 5;
struct LCT {
protected:
struct node {
node *ch[2], *fa;
int rev;
node(int rev = 0): rev(rev) { ch[0] = ch[1] = fa = NULL; }
bool ntr() { return fa && (fa->ch[1] == this || fa->ch[0] == this); }
bool isr() { return fa->ch[1] == this; }
void trn() { std::swap(ch[0], ch[1]); rev ^= 1; }
void dwn() { if(rev) { if(ch[0]) ch[0]->trn(); if(ch[1]) ch[1]->trn(); rev = 0; } }
}s[maxn], *t[maxn], *lst;
int top;
void rot(node *x) {
node *y = x->fa, *z = y->fa; int k = x->isr(); node *w = x->ch[!k];
if(y->ntr()) z->ch[y->isr()] = x;
x->ch[!k] = y, y->ch[k] = w;
y->fa = x, x->fa = z;
if(w) w->fa = y;
}
void splay(node *o) {
t[top = 1] = o;
while(t[top]->ntr()) t[top + 1] = t[top]->fa, top++;
while(top) t[top--]->dwn();
while(o->ntr()) { if(o->fa->ntr()) rot(o->isr() ^ o->fa->isr()? o : o->fa); rot(o); }
}
void access(node *x) { for(node *y = NULL; x; x = (y = x)->fa) splay(x), x->ch[1] = y, lst = x; }
void makeroot(node *x) { access(x), splay(x), x->trn(); }
node *findroot(node *x) { access(x), splay(x); while(x->dwn(), x->ch[0]) x = x->ch[0]; return splay(x), x; }
node *getLCA(node *x, node *y) { return access(x), access(y), lst; }
void link(node *x, node *y) { makeroot(x), x->fa = y; }
public:
void link(int x, int y) { link(s + x, s + y); }
int LCA(int x, int y) { return getLCA(s + x, s + y) - s; }
void makeroot(int x) { makeroot(s + x); }
}v;
int main() {
int n = in(), m = in(), s = in();
for(int i = 1; i < n; i++) v.link(in(), in());
v.makeroot(s);
while(m --> 0) printf("%d\n", v.LCA(in(), in()));
return 0;
}
P3379 【模板】最近公共祖先(LCA)(LCT)的更多相关文章
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)
Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...
- POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)
POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- 【lhyaaa】最近公共祖先LCA——倍增!!!
高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...
- 【洛谷 p3379】模板-最近公共祖先(图论--倍增算法求LCA)
题目:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 解法:倍增. 1 #include<cstdio> 2 #include<cstdlib> 3 #include ...
- 最近公共祖先(LCA)模板
以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖 ...
- HDU 2586 How far away ?(LCA模板 近期公共祖先啊)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...
- luogu3379 【模板】最近公共祖先(LCA) 倍增法
题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤:1.使两个点深度相同:2.使两个点相同. 这两个步骤都可用倍增法进行优化.定义每个节点的Elder[i]为该节点的2^k( ...
- 最近公共祖先lca模板
void dfs(int x,int root){//预处理fa和dep数组 fa[x][0]=root; dep[x]=dep[root]+1; for(int i=1;(1<<i)&l ...
随机推荐
- 1104 Sum of Number Segments
题意: 给出n个不大于1.0的小数序列,如{ 0.1, 0.2, 0.3, 0.4 },则共有10个分片(0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, ...
- c语言-构建一个静态二叉树
第一.树的构建 定义树结构 struct BTNode { char data; struct BTNode* pLChild; struct BTNode* pRChild; }; 静态方式创建一个 ...
- 2016.9.9《Oracle查询优化改写技巧与案例》电子工业出版社一书中的技巧
1.coalesce (c1,c2,c3,c4,...) 类似于nvl但可以从多个表达式中返回第一个不是null的值 2.要在where条件中引用列的别名,可以再嵌套一层查询 select * fro ...
- ORACLE——日期时间格式化参数详解 之三
2.20 Y,YYY 返回有逗号分隔显示的年 SQL> select to_char(SYSTIMESTAMP,'Y,YYY') from dual; TO_CHAR(SYSTIMESTAMP, ...
- c# 代码调用ssis包
https://docs.microsoft.com/en-us/sql/integration-services/run-manage-packages-programmatically/loadi ...
- 什么是Scatter/Gather?
scatter/gather指的在多个缓冲区上实现一个简单的I/O操作,比如从通道中读取数据到多个缓冲区,或从多个缓冲区中写入数据到通道: scatter(分散):指的是从通道中读取数据分散到多个缓冲 ...
- 今天出现编码出现了No suitable driver found for jdbc
出现这样的情况,一般有四种原因: 一:连接URL格式出现了问题(Connection conn=DriverManager.getConnection("jdbc:mysql://local ...
- linux 监控内存介绍
一:系统监控:1.对cpu的监测:查看进程占用内存情况 top pid user PRI NI size RSS share stat 进程号 进程所属用户 优先级 优先级 进程所占空间 使用物理内存 ...
- 关于c#数据类型,类型转换,变量,常量,转义符。。。
先说一下数据类型...数据类型可以分为两大类:基本数据类型和引用类型. 基本数据类型按功能又分为“值类型”,“布尔型”,“字符型”. 引用类型分为“字符串”,“时间日期”. 没图没真相↓面放图. 橙 ...
- 1020C Elections
传送门 题目大意 现在有 n个人,m个党派,第i个人开始想把票投给党派pi,而如果想让他改变他的想法需要花费ci元.你现在是党派1,问你最少花多少钱使得你的党派得票数大于其它任意党派. 分析 我们枚举 ...