【模板】树链剖分求LCA

洛谷3379

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=500010,inf=1e9;
 5 int n,m,x,y,root,tot,dep[maxn],son[maxn],size[maxn],fa[maxn],top[maxn],last[maxn];
 6 struct edge{int to,pre;}e[maxn<<1];
 7 inline void read(int &k){
 8     k=0; int f=1; char c=getchar();
 9     while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
10     while(‘0‘<=c&&c<=‘9‘)k=k*10+c-‘0‘,c=getchar();
11     k*=f;
12 }
13 void add(int x,int y){e[++tot].to=y; e[tot].pre=last[x]; last[x]=tot;}
14 void dfs1(int x){
15     size[x]=1; dep[x]=dep[fa[x]]+1;
16     for (int i=last[x],to;i;i=e[i].pre)
17     if ((to=e[i].to)!=fa[x]){
18         fa[to]=x; dfs1(to);
19         size[x]+=size[to];
20         if (size[to]>size[son[x]]) son[x]=to;
21     }
22 }
23 void dfs2(int x,int tp){
24     top[x]=tp;
25     if (son[x]) dfs2(son[x],tp);
26     for (int i=last[x],to;i;i=e[i].pre)
27     if ((to=e[i].to)!=fa[x]&&to!=son[x]) dfs2(to,to);
28 }
29 int lca(int x,int y){
30     int f1=top[x],f2=top[y];
31     while(f1!=f2){
32         if (dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
33         x=fa[f1]; f1=top[x];
34     }
35     return dep[x]<dep[y]?x:y;
36 }
37 int main(){
38     read(n); read(m); read(root);
39     for (int i=1;i<n;i++) read(x),read(y),add(x,y),add(y,x);
40     dfs1(root); dfs2(root,root);
41     for (int i=1;i<=m;i++) read(x),read(y),printf("%d\n",lca(x,y));
42     return 0;
43 }

时间: 2024-10-07 18:24:28

【模板】树链剖分求LCA的相关文章

P2633|主席树+dfs序+树链剖分求lca+离散化

不知道为什么会RE.. 待补 思路:链上求u和v两点路径第k小利用lca就转变为了 U+V-LCA-FA(LCA) 上的第k小,这因为每个点的主席树的root是从其父转移来的.可以用树链剖分求lca:在dfs序上建立主席树将树上问题转变为区间问题,询问的时候用主席树求区间k小值. 终于能写出这种题了,开心! #include<bits/stdc++.h> using namespace std; const int maxn = 1e5+100; int n,m,e = 1,num,ans=0

树链剖分求LCA

这里先推荐两道练习的裸题 首先是求点 [codevs4605] LCA 就是求两个点的公共祖先,每次询问xor上上一个询问的答案. 先是两遍DFS: dfs1:把dep.siz.son求出来 dfs2:求出top和w siz[v]表示以v为根的子树的节点数 dep[v]表示v的深度(根深度为1) top[v]表示v所在的链的顶端节点 fa[v]表示v的父亲 son[v]表示与v在同一重链上的v的儿子节点 w[v]结点编号 int lca(int x,int y){ while (top[x]!=

【POJ1330】Nearest Common Ancestors(树链剖分求LCA)

Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of

[模板] 树链剖分找LCA

#include <cstdio> #include <cstring> #define MAX 500005 int d[MAX],fa[MAX],size[MAX],top[MAX],son[MAX]; int N,M,S,tot=0; int head[MAX]; struct edge{ int v,next; }G[MAX<<1]; inline void add(int u,int v){ G[++tot].v=v;G[tot].next=head[u];h

[luogu P3384] [模板]树链剖分

[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数

luoguP3384 [模板]树链剖分

luogu P3384 [模板]树链剖分 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> #include<ctime> #include<queue> #define rg register

BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=2243 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写

[模板]树链剖分

原题链接:https://www.luogu.org/problemnew/show/P3384 树链剖分+线段树,备用. 等待补充详细解释中. /* 1 x y z x到y最短路径上加上z 2 x y 求x到y的最短路径上的节点值之和 3 x z 以x为根节点的子树内的所有节点值都加上z 4 x 以x为根节点的所有节点值之和 */ #include<cstdio> void read(int &y) { y=0;char x=getchar();int f=1; while(x<

模板 树链剖分BFS版本

//点和线段树都从1开始 //边使用vector vector<int> G[maxn]; int dfs_clock,que[maxn*2],num[maxn],iii[maxn],b[maxn],a[maxn],top[maxn],deep[maxn],fa[maxn],idx[maxn]; //采用静态链表 //a[i] 是初始时树上每个点的权值 //b[i] 是经过bfs后每个点的权值 //idx[i] 是每个点在全局线段树中的下标 void build_List() { int ft