lca

Linux认证浅析

吃可爱长大的小学妹 提交于 2020-04-07 02:34:20
-------------------------------------------------------------------------------- 现在各公司对Linux的关切程度日益高涨,这促使越来越多的IT专业人员试图掌握这个企鹅操作系统的相关知识和经验。最近由NetAdmin组织的一次调查结果(图A)表明,大量的IT技术人员都正在考虑通过Linux认证考试,为了帮助你做出选择,我们现在就来看一看Linux认证领域的现状,提出可供你选择的头4号Linux资格认证计划。 -------------------------------------------------------------------------------- Linux Professional Institute 目前,Linux Professional Institute(LPI)已经先期推出了Linux Professional Institute Certified-Level 1 (或者简称为LPIC-1)认证计划。不久的将来还会按预定计划推出第2和第3级认证。为了获得LPIC-1证书,你必须通过两门各自长达 90分钟的考试-101 (LPI General Linux, Part 1)和102(LPI General Linux, Part 2)。LPI的LPIC

【学习笔记】倍增LCA

蓝咒 提交于 2020-04-06 20:57:12
LCA问题:给定一颗 \(n\) 个结点的有根树,有 \(m\) 次询问,每次询问给出结点 \(a,b\) ,求 \(a,b\) 的最近公共祖先。此类问题通称 LCA 。 暴力 一次一次把 \(a,b\) 向上提,知道 \(a\) 与 \(b\) 相等为止。 倍增加速 在上面暴力的思想中,是 一步一步 向上跳的。 倍增的核心思想就是 \(2^j\) 步 \(2^j\) 步向上跳。 我们需要先处理出第 \(i\) 个点的第 \(2^j\) 个祖先。 如何求出? 设 \(f_{i,j}\) 为第 \(i\) 个点向上跳 \(2^j\) 后所处的位置,根据初一学习的幂的性质,我们认为第 \(i\) 个点向上跳 \(2^j\) 后所处的位置就是第 \(i\) 个点向上跳 \(2^{j-1}\) 后再向上跳 \(2^{j-1}\) ( \(2^{j-1}+2^{j-1}=2^j\) )。 所以我们有: \[\text{令}x=f_{i,j-1},\text{则} f_{i,j}=f_{x,j-1} \] 可以递推出来: void dfs(int u, int fa) //当前是第 u 个结点,u 的父亲是 fa { d[u] = d[fa]+1; /顺便计算深度 for(int i=1; (1<<i) <= d[u]; i++) //(1<<i)就是 2^i

tarjan算法求最近公共祖先

陌路散爱 提交于 2020-04-04 04:20:32
tarjian算法 LCA: LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点。也就是说,在两个点通往根的道路上,肯定会有公共的节点,我们就是要求找到公共的节点中,深度尽量深的点。还可以表示成另一种说法,就是如果把树看成是一个图,这找到这两个点中的最短距离。 LCA算法有在线算法也有离线算法,所谓的在线算法就是实时性的,而离线算法则是要求一次性读入所有的请求,然后在统一得处理。而在处理的过程中不一定是按照请求的输入顺序来处理的。说不定后输入的请求在算法的执行过程中是被先处理的。 tarjan算法。这个算法是基于并查集和DFS的。离线算法。 现在我们来观察正在处理与x结点关联的询问时并查集的情况。由于一个结点处理完毕后,它就被归到其父结点所在的集合,所以在已经处理过的结点中(包括 x本身),x结点本身构成了与x的LCA是x的集合,x结点的父结点及以x的所有已处理的兄弟结点为根的子树构成了与x的LCA是father[x]的集合,x结点的父结点的父结点及以x的父结点的所有已处理的兄弟结点为根的子树构成了与x的LCA是father[father[x]]的集合……(上面这几句话如果看着别扭,就分析一下句子成分,也可参照右面的图)假设有一个询问(x,y)(y是已处理的结点),在并查集中查到y所属集合的根是z,那么z

LCA算法总结

别来无恙 提交于 2020-04-04 04:19:15
LCA问题(Least Common Ancestors,最近公共祖先问题),是指给定一棵有根树T,给出若干个查询LCA(u, v)(通常查询数量较大),每次求树T中两个顶点u和v的最近公共祖先,即找一个节点,同时是u和v的祖先,并且深度尽可能大(尽可能远离树根)。 LCA问题有很多解法:线段树、Tarjan算法、跳表、RMQ与LCA互相转化等。 一 LCA问题 LCA问题的一般形式:给定一棵有根树,给出若干个查询,每个查询要求指定节点u和v的最近公共祖先。 LCA问题有两类解决思路: 在线算法,每次读入一个查询,处理这个查询,给出答案。 离线算法,一次性读入所有查询,统一进行处理,给出所有答案。 一个LCA的例子如下。比如节点1和6的LCA为0。 二、Tarjan算法 Tarjan算法是离线算法,基于后序DFS(深度优先搜索)和并查集。 算法从根节点root开始搜索,每次递归搜索所有的子树,然后处理跟当前根节点相关的所有查询。 算法用集合表示一类节点,这些节点跟集合外的点的LCA都一样,并把这个LCA设为这个集合的祖先。当搜索到节点x时,创建一个由x本身组成的集合,这个集合的祖先为x自己。然后递归搜索x的所有儿子节点。当一个子节点搜索完毕时,把子节点的集合与x节点的集合合并,并把合并后的集合的祖先设为x。因为这棵子树内的查询已经处理完

最近公共祖先LCA Tarjan算法

冷暖自知 提交于 2020-04-04 04:18:28
LCA算法: LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点。也就是说,在两个点通往根的道路上,肯定会有公共的节点,我们就是要求找到公共的节点中,深度尽量深的点。还可以表示成另一种说法,就是如果把树看成是一个图,这找到这两个点中的最短距离。 LCA算法有在线算法也有离线算法,所谓的在线算法就是实时性的,比方说,给你一个输入,算法就给出一个输出,就像是http请求,请求网页一样。给一个 实时的请求,就返回给你一个请求的网页。而离线算法则是要求一次性读入所有的请求,然后在统一得处理。而在处理的过程中不一定是按照请求的输入顺序来处理 的。说不定后输入的请求在算法的执行过程中是被先处理的。 本文先介绍一个离线的算法,就做tarjan算法。这个算法是基于并查集和DFS的。Dfs的作用呢,就是递归,一次对树中的每一个节点进行处理。而并查集的作用就是当dfs每访问完(注意,这里是访问完)到一个点的时候,就通过并查集将这个点,和它的子节点链接在一起构成一个集合,也就是将并查集中的pnt值都指向当前节点。这样就把树中的节点分成了若干个的集合,然后就是根据这些集合的情况来对输入数据来进行处理。 比方说当前访问到的节点是u,等u处理完之后呢,ancestor[u]就构成了u的集合中的点与u点的LCA,而ancestor[fa[u]]就构成

LCA最近公共祖先

不羁岁月 提交于 2020-03-27 09:20:46
1.ST表+时间戳 DFS记录这棵树每个点出现的时间1 2 3 2 4 2 5 2 1 6 7 8 7 6 1。 然后用ST表记录每个区间的min值,然后进行q次查询,时间复杂度O(Nlog2N+Qlog2N); #include<iostream> #include<stdio.h> #include<stdlib.h> #include <iomanip> #include<cmath> #include<float.h> #include<string.h> #include<algorithm> #define sf scanf #define scf(x) scanf("%d",&x) #define scff(x,y) scanf("%d%d",&x,&y) #define pf printf #define prf(x) printf("%d\n",x) #define mm(x,b) memset((x),(b),sizeof(x)) #include<vector> #include<queue> #include<map> #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=a;i>=n;i--) typedef long long ll; const ll mod=1e9

P3379 【模板】最近公共祖先(LCA)

社会主义新天地 提交于 2020-03-27 05:45:12
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。 输入输出格式 输入格式: 第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。 接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。 接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果。 输入输出样例 输入样例#1: 复制 5 5 4 3 1 2 4 5 1 1 4 2 4 3 2 3 5 1 2 4 5 输出样例#1: 复制 4 4 1 4 4 说明 时空限制:1000ms,128M 数据规模: 对于30%的数据:N<=10,M<=10 对于70%的数据:N<=10000,M<=10000 对于100%的数据:N<=500000,M<=500000 样例说明: 该树结构如下: 第一次询问:2、4的最近公共祖先,故为4。 第二次询问:3、2的最近公共祖先,故为4。 第三次询问:3、5的最近公共祖先,故为1。 第四次询问:1、2的最近公共祖先,故为4。 第五次询问:4、5的最近公共祖先,故为4。 故输出依次为4、4、1、4、4。 用tarjan写的,第一次用读入优化 异或运算很巧妙,但是要注意cnt要从1开始 find函数也要优化

LCA最近公共祖先

冷暖自知 提交于 2020-03-27 02:29:06
不会 准备研究一波!!! 1 #include<bits/stdc++.h> 2 const int maxn = 500010; 3 using namespace std; 4 vector<int> g[maxn]; 5 int par[20][maxn], dep[maxn], n, m, ml; 6 void dfs(int v, int p, int d) 7 { 8 par[0][v] = p; 9 dep[v] = d; 10 for (int i = 0; i < g[v].size(); ++i){ 11 if (g[v][i] != p) dfs(g[v][i], v, d + 1); 12 } 13 return ; 14 } 15 void init(int v) 16 { 17 dfs(v, -1, 0); 18 int sum = 1; 19 while (sum <= n) sum <<= 1, ++ml; 20 for (int k = 0; k < ml; ++k){ 21 for (int v = 1; v <= n; ++v){ 22 if (par[k][v] == -1) par[k + 1][v] = -1; 23 else par[k + 1][v] = par[k][par[k][v]]; 24 } 25 } 26 return ;

LCA最近公共祖先(倍增版)

牧云@^-^@ 提交于 2020-03-27 02:03:56
倍增版LCA lac 即最近公共祖先,u和v最近公共祖先就是两节点公用的祖先中深度最大的 比如 其中 lca(1,2)=4, lca(2,3)=4, lca(3,5)=1, lca(2,5)=4; 如何求LCA? 树上倍增版: 预处理每一个节点的深度 depth[i] ; 选定两节点; 将深度大的节点往上跳,跳到与另一节点相同深度; 然后两个节点一起往上跳,直到两个节点重合; 那么这个节点就是两个节点的lca; 那么怎么让计算机实现“跳”? 我们可以用倍增思想 设 f[i][j] 表示第i个节点往上跳2^j个节点所到达的祖先 那么 f[i][j]=f[f[i][j-1]][j-1] 意思是 从i往上跳2 j个节点所到达的节点可以转化为从i往上跳2 (j-1)再往上跳2^(j-1)个,而f[i][j-1]在之前通过递推已经推出来了 初始化Code: void init() { for(int j=1;j<=N;j++) { for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1]; } } 题目 给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。 输入格式: 第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。 接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树

BZOJ - 3730 震波 (点分树+树状数组)

和自甴很熟 提交于 2020-03-18 13:45:08
两种操作: 1.查询与树上结点x距离不超过k的结点权值之和 2.将结点x的权值修改为y 点分树模板题。 首先考虑一种比较暴力的做法:用树形dp的思想,将树转化成有根树,设f[u][k]为结点u子树下与其距离不超过k的点权和,则ans(x,k)=f[u][k]+f[fa[u]][k-1]-f[u][k-2]+f[fa[fa[u]]][k-2]-f[fa[u]][k-3]...,可如果树太高的话就GG了,要是能把树高变成logn级别的就好了。 建立点分树(点分治过程中形成的树),每个结点维护两个树状数组,一个维护以该结点为重心的各个距离上的权值和,一个维护其虚父亲(点分树上的父亲)在“该结点方向”上的各个距离上的权值和(用于容斥)。还要另外维护一个数据结构用于求原树上两点之间距离(树剖效率比较高),修改和询问就从当前结点开始不断向上跳即可。(点分树的树高是logn级别的,可以暴力往上跳) 总复杂度$O(nlogn+qlog^2n)$ 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,inf=0x3f3f3f3f; 5 struct E {int v,nxt;} e[N<<1]; 6 int a[N],hd[N],ne,n,Q,siz[N],mx[N]