LCA 与 RMQ

LCA与RMQ问题详解 LCA问题与RMQ问题详解 1.问题描述    LCA:Least Common Ancestors(最近公共祖先)。对于一棵树 T 中的任意两个节点u,v,算法 x=LCA(T, u, v) 返回的结果为节点u,v的最近公共父节点,也即是离树T的根节点最远的节点x,使得x同时是u和v的祖先。       例子:对于T=(V,E) V={1,2,3,4,5,6,7,8,9,10,11,12, 阅读详情

求LCA可以用tarjan算法(见代码); 这里不详细介绍了。用到的东西主要是dfs + 并查集。 详见最下面的代码。

还有一种方法是利用 倍增的思想 求。

具体就是:  

 f[i][j] 表示i的第2^j次方个祖先是谁。 则f[i][j]= f[ f[i][j-1] ][j-1]; (j>0)        f[i][j]=father[i];(j==0)  

这样可以处理出每个节点的2^j次方的祖先是谁。然后对于每个询问p和q的LCA是谁。我们先考虑一种简单的情况:p和q在树的同一层(设为h)。让j>=log(h); 然后比较f[p][j]与f[q][j]是否相等,如果不等,则LCA(p,q)肯定在更高的层上。令p=f[p][j],q=f[q][j]; j--;   如果相等,j--;  这样用类似于二分的方法,可以求出LCA;

如果p和q不在同一层,假设h(p) > h(q);  可以先求出与q在同一层的p的祖先,然后用上面的办法求LCA。 怎么求与q在同一层的p的祖先呢? 可以用二分的方法来求。

for (log = 1; 1 << log <= h[p]; log++);    log--;  for (i = log; i >= 0; i--)  if(h[p] - (1 << i) >= h[q])  p =f[p][i];

求RMQ有ST算法,思想与上面的差不多。 r[i][j]表示从第i位数字开始到第i+2^j-1位 中值最小的数字。 则 r[i][j] = min ( r[i][j-1] ,r[i+2^(j-1)][j-1] ).  初始化为 r[i][0] = a[i];

然后对于每组询问p和q。k=log(q-p+1) ;    rmq( p, q) =  min {  r( p,k) ,r( q-2^k+1, k )  }

#include<stdio.h>  // poj 3264
#include<math.h>
#define max(x,y)  ((x)>(y)?(x):(y))
#define min(x,y)  ((x)<(y)?(x):(y))
int r[50010][50],s[50010][50]; int a[50010];
int n;

void initial()
{
    int i,j,k;
    for(i=1;i<=n;i++)
        r[i][0]=s[i][0]=a[i];
    for(j=1;1<<j<=n;j++)
        for(i=1;i+(1<<j)-1<=n;i++)
        {
            r[i][j]=min( r[i][j-1],r[i+(1<<(j-1))][j-1] );
            s[i][j]=max( s[i][j-1],s[i+(1<<(j-1))][j-1] );
        }
}

int main()
{
    int q,i,j,k; int u,v; int maxh,minh;
    scanf("%d%d",&n,&q);
    for(i=1;i<=n;i++)  scanf("%d",a+i);
    initial();
    for(i=1;i<=q;i++)
    {
        scanf("%d%d",&u,&v);
        if(u==v) { printf("0\n"); continue; }
        j=(v-u+1);
        k=int(log10((double)j)/log10(2.0));
        minh=min( r[u][k],r[v-(1<<k)+1][k] );
        maxh=max( s[u][k],s[v-(1<<k)+1][k] );
        printf("%d\n",maxh-minh);
    }
    return 0;
}


 

至此,已经分别说了LCA和RMQ的算法。其实LCA和RMQ问题是等价的,即RMQ问题和LCA问题可以相互转换。下面就来简单说一说,怎么去转换两个问题;

一, LCA --> RMQ

可以通过dfs将树形结构转换为线形结构,得到欧拉序列。记录每个节点第一次出现的位置。 可以知道两个节点的LCA必定在这两个节点出现位置的中间,而且是深度最低的节点。我们在dfs的过程中可以记录每个点的深度。因此两个节点的LCA就转化为求对应的深度序列中两个位置间的最小值了。这就是RMQ了。由于深度序列每相邻两个元素间相差为1,所以叫做正负1RMQ。( 正负1RMQ是可以在O(N)的时间复杂度内求解的,主要就是把序列分快了,具体的我还没认真看)

二,RMQ---> LCA

构造笛卡尔树。具体构造过程忽略(可以上网搜),然后就转化为了LCA。(  然后再用一的方法再转化为RMQ时就转化为正负1RMQ了 ,就可以在O(N)时间内求解了 )


下面借用了别人的总结展示一下各个算法的时间复杂度:

 



所以说,LCA和RMQ问题是等价的,都可以做到在O(N)的时间内求解。如果题目时间要求没那么高,就不用这样转来转去的了。

下面是tarjan算法求LCA。(poj 1330)

 

#include<stdio.h>    //poj 1330
#include<vector>
using namespace std;
intf[10010],r[10010];
vector<int>tree[10010]; int n;
intindegree[10010];  intvis[10010],ans[10010];
int s,t;   //存储询问,该题只有一组询问
 
void initial()
{
    int i;
    for(i=1;i<=n;i++)
    {
        tree[i].clear();
        f[i]=i; ans[i]=i; vis[i]=0;
        r[i]=1;
        indegree[i]=0;
    }
}
 
int find(int x)
{
    if( f[x]==x )
        return f[x];
    return f[x]=find(f[x]);
}
 
int Unionset(intx,int y)   // 按秩合并
{
    int fx,fy;
    fx=find(x); fy=find(y);
    if(fx==fy) return 0;
    if( r[fx] <= r[fy] )
    {
        f[fx]=fy;
        r[fy]+=r[fx];
    }
    else
    {
        f[fy]=fx;
        r[fx]+=r[fy];
    }
    return 1;
}
 
void LCA(int u)
{
    int len,i,j;
    ans[u]=u;
    len=tree[u].size();
    for(i=0;i<len;i++)
    {
        LCA(tree[u][i]);
        Unionset(u,tree[u][i]);
        ans[find(u)]=u;
    }
    vis[u]=1;
    if ( ( u==s && vis[t]==1) )
        printf("%d\n",ans[find(t)]);
    else
        if( (u==t && vis[s]==1) )
           printf("%d\n",ans[find(s)]);
}
 
int main()
{
    int T,i,j; int u,v;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        initial();
        for(i=1;i<n;i++)
        {
           scanf("%d%d",&u,&v);
            tree[u].push_back(v);
            indegree[v]++;
        }
        scanf("%d%d",&s,&t);
        for(i=1;i<=n;i++)
            if( indegree[i]==0 )
            {
                LCA(i); break;
            }
    }
    return 0;
}

LCA 转 RMQ算法 【总结】 首先,在你看这个算法之前,要确保你理解了RMQ的 ST 算法。 但是不理解没关系啊,提供通道:  点我 声明:这是方便我以后复习用的,所以总结不是特别详细。 LCA - 最近公共祖先:在有根树中,两个节点u和v的公共祖先中距离最近的那个点。 上图理解: 如图,我们想要求出LCA(4,7),LCA(8,6),LCA(5,8)。 用LCA转R 阅读详情

相关推荐

【模板】LCA(欧拉序+RMQ)

平常在信息学竞赛中求LCA一般有三种办法: 用倍增法求解,预处理复杂度是 O(nlogn)O(nlog⁡n)O(n\log n) ,每次询问的复杂度是 O(logn)O(log⁡n)O(\log n), 属于在线解法。 利用欧拉序转化为RMQ问题,用 ST表 求解RMQ问题,预处理复杂度 O(n+nlogn)O(n+nlog⁡n)O(n + n \log n) ,每次询问的复杂度为 O(1)O...

夕弦 3425

免费PPT资源站点全整理:模板、图片、图标、字体、配色一文搞定

PPT制作绕不开素材资源,但很多人误以为免费就代表低质或版权不明。实际上,高效的资源获取逻辑不是死磕模板,而是拆解图片、图标、字体与配色等要素,从免费可商用的图库、开源字体平台与图标库中组合出高品质设计。掌握这些资源的检索与使用准则,不但能规避侵权风险,还能大幅提升职场汇报、毕业答辩等场景的产出效率。本文整理了一套经过实践验证的免费PPT资源站点清单,覆盖模板、高清图片、图标、中文字体与配色方案,帮你建立个人专属素材池,从此告别付费套路和模糊水印。

weixin_34302561的博客 720

Jetson编译安装pycuda

可使用nvcc --version查看是否有信息输出,若没有,且安装cuda的情况下,需要手动将CUDA 的路径添加到环境变量中。编译生成_pvt_struct.cpython-38-aarch64-linux-gnu.so文件。基于jetson orin nano jetpack512模块上安装pycuda。4、获取pycuda源码(版本根据实际情况获取)2、进入conda环境并安装cuda工具包。9、若未检测出来需要清除并强制编译。7、编译成功后安装pycuda。5、配置编译并设置环境变量。

qq_48175141的博客 972

算法之LCA与RMQ问题

1、  概述 LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先)。 RMQ(Range Minimum/Maximum Query),即区间最值查询,是

zh_qd1014的专栏 1381

HX720数据采集实战:从硬件连接到姿态解析(含避坑指南)

本文详细介绍了HX720高精度ADC芯片在数据采集与姿态解析项目中的实战应用。内容涵盖从硬件电路设计、驱动源码编写与优化,到原始数据处理、校准以及最终姿态角度计算的完整流程,并提供了关键的避坑指南和调试技巧,帮助开发者高效完成从传感器信号到可用姿态数据的转换。

i8j9k0l1的博客 487

从Palantir到AI时代:Forward Deployed Engineer模式的深度解析

《从Palantir到AI时代:FDE模式的创新与挑战》摘要:Palantir开创的前置部署工程师(FDE)模式正在成为AI创业公司的标配。该模式通过现场工程师深入了解客户需求,填补产品与实际应用间的鸿沟,颠覆了传统SaaS规模化路径。核心优势在于将定制化服务转化为产品发现机制,特别适合高度异质化的AI市场。成功关键在于平衡定制与标准化,通过合同价值增长、产品杠杆效应等独特指标衡量成效。FDE人才需要兼具领域洞察力与快速原型能力。这一模式表明,在AI等新兴领域,深入客户现场可能比单纯追求技术突破更能创造商业

老孙 | Ethan Sun 的博客:AI 智能体与 AI 原生软件的工程实践 4535

零零散散学算法之详解RMQ & LCA

深入理解RMQ & LCA 正文 第一节 RMQ、LCA概述 LCA:LowestCommonAncestor,译为最近公共祖先。其解释就是说:在有根树中,找出树中任意两个节点最近的公共祖先,或者说找到任意两个节点离树根最远的公共祖先。 RMQ:RangeMinimumQuery,译为区间最小值查...

weixin_33775582的博客 294

基于拟蒙特卡洛模拟法的随机潮流计算matlab程序

由式(4-11)可知,蒙特卡洛模拟法的计算量不受电力系统规模大小影响,因此该方法在一些复杂的电力系统中可以得到应用,包括处理电力系统中有多个间歇性新能源接入的问题,解决系统中多个节点之间相关性问题等等。本章在此基础上提出了基于拟蒙特卡洛模拟的随机潮流计算方法,并且对拟蒙特卡洛法中的拟随机数序列进行了改进,大大提高了随机潮流的计算效率。模拟法的具体思路如下:基于实际工程问题的求解需要,建立与之相对应的随机模拟过程和随机概率模型,使得它们的参数,包括概率分布或者数学期望,能够等于问题的实际解;

weixin_47365903的博客 1794

倍增算法讲解——序列、RMQ和LCA

讲解倍增算法关于序列、RMQ和LCA的应用

qq_57150526的博客 3250

Windows Server 2012 R2虚拟机安装全攻略:从镜像选择到网络配置一步到位

本文提供Windows Server 2012 R2虚拟机安装全攻略,涵盖从镜像选择到网络配置的完整流程。详细讲解在Oracle VM VirtualBox中的安装步骤、TCP/IP网络设置、系统优化及常见问题解决方案,帮助用户快速搭建可立即投入使用的服务器环境。特别适合IT初学者和系统管理员学习传统服务器应用的部署与配置。

weixin_28363123的博客 538

什么是垂直同步?电脑快速消除屏幕撕裂与提升游戏性能的方法 垂直同步、游戏画面撕裂、游戏优化、VSync、FPS、FreeSync、G-Sync、显卡驱动更新、游戏画质、输入延迟

看这张动图,左边的画面出现了明显“切开”的断层现象,而右边画面非常流畅,没有撕裂。这正是「垂直同步」开关的区别。:每秒生成多少帧图像。比如 60FPS 表示一秒钟显示 60 张图片。刷新率(Refresh Rate):显示器每秒刷新几次画面,单位是赫兹(Hz)。60Hz 表示每秒刷新 60 次。参数说明FPS显卡渲染速度(逻辑帧率)刷新率显示器的显示频率(物理限制)当 FPS 高于刷新率时,显卡渲染的画面来不及被显示器显示,导致撕裂。屏幕撕裂(Screen Tearing)

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1346

RMQ和LCA

RMQ和LCA 【内容简介】   讨论解决RMQ、LCA问题的算法、以及RMQ、LCA两类问题的相互转换。它们在字符串处理和生物学计算中有着广泛应用,在信息学奥赛中更是被广泛应用和扩展,所以熟练掌握RMQ和LCA问题就显得十分重要。 ※在内容开始,我们假设一个算法预处理时间为 f(n),查询时间为g(n)。这个算法复杂度的标记为(或f(n)-g(n))。 【关键词】RMQ、LCA、ST

1238

从业务角色到工作台:一步步创建 SAP Fiori Launchpad Space 与 Page

SAP S/4HANA Launchpad 配置优化指南:从业务角色出发构建高效工作台 本文针对S/4HANA项目中用户普遍反映的"入口难找"问题,提出基于Spaces和Pages的系统化解决方案。通过"以工作岗位为中心"的设计理念,将Launchpad信息架构重构为:一个业务角色对应一个Space,每个Space包含1-5个Page,Page内按任务划分2-5个Section,每个Section放置3-7个Tiles。文章详细阐述了从Business Role入手配

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 224

RMQ、LCA

..

nameofcsdn的博客 7027

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

RMQ & LCA

第一节RMQ、LCA概述 LCA:LowestCommonAncestor,译为最近公共祖先。其解释就是说:在有根树中,找出树中任意两个节点最近的公共祖先,或者说找到任意两个节点离树根最远的公共祖先。 RMQ:RangeMinimumQuery,译为区间最小值查询。其解释就是说:对于含有N个元素的数列A,在数列中找到两个指定索引之间的最小值及最小值的位置。 第...

sxy201658506207的博客 387

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

日常题解——LCA和RMQ1

这个代码没有具体的建树,只有核心的代码原理和代码实现,建树用python的邻接表最方便,遍历子节点部分参照Python遍历邻接表逻辑理解。

xiaoyu524的博客 780

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

LCA转RMQ

#include &lt;bits/stdc++.h&gt; using namespace std; const int N = 40010; const int M = 25; int dp[2*N][M]; //这个数组记得开到2*N,因为遍历后序列长度为2*n-1 bool vis[N]; struct edge{int u,v,w,next;}e[2*N]; int tot,head...

cj1064789374的博客 290

LCA与RMQ算法

1、 概述 LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先)。 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大

Follow My Heart 591

RMQ和LCA在线算法

原文 学习一下LCA的在线算法。RMQRMQ是查询区间最值的一种方法,其思想非常简单。举例来说,我们想查询区间[5,37][5,37]中的最小值,如果我们事先知道区间[5,5+24)[5,5+2^4)中的最小值以及区间[37−24+1,37+1)[37-2^4+1,37+1)中的最小值,那么我们很容易得到答案。于是问题就变为,我们如何知道区间[i,i+2k)[i,i+2^k)中的最小值。显然Min

kjcsdnblog的专栏 548

LCA转RMQ 模版及解析 + LCA倍增法模版

九野的博客,转载请注明出处:http://blog.youkuaiyun.com/acmmmm/article/details/15490519   LCA:  最近公共祖先 则 LCA(2,3) = 2 ; LCA(3,4) = 5; LCA(1,2) = 5; LCA(1,5) = 5;   RMQ: 区间最值问题, 给定一组数,在O(logn) 的复杂度内回答区间的最值 (一般采用线段树

九野的博客 5736

LCA和RMQ算法

RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干次询问RMQ(i,j),返回数列A中下标在区间[i,j]中的最小/大值。 本文介绍一种比较高效的ST算法解决这个问题。ST(Sparse Table)算法可以在O(nlogn)时间内进行预处理,然后在O(1)时间内回答每个查询。 1)预处理 设A[i]是要求...

wa的一声就哭了 481

Lca与Rmq

关于LCA和RMQ问题 一、最近公共祖先(Least Common Ancestors) 对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。另一种理解方式是把T理解为一个无向无环图,而LCA(T,u,v)即u到v的最短路上深度最小的点。 这里给出一个LCA的例子: 例一 对于T=<V,E>V={1,...

179

详解RMQ & LCA

第一节 RMQ、LCA概述          LCA:Lowest Common Ancestor,译为最近公共祖先。其解释就是说:在有根树中,找出树中任意两个节点最近的公共祖先,或者说找到任意两个节点离树根最远的公共祖先。          RMQ:Range Minimum Query,译为区间最小值查询。其解释就是说:对于含有N个元素的数列A,在数列中找到两个指定索引

xyjikl 734

RMQ与LCA

1.概述   LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先)。   RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下...

bachoupu4590的博客 177

LCA与RMQ的相互转换

一、最近公共祖先(LeastCommon Ancestors) 对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。另一种理解方式是把T理解为一个无向无环图,而LCA(T,u,v)即u到v的最短路上深度最小的点。这

lilongherolilong的专栏 1613
上一篇: 树形dp 求期望 HDU4035
下一篇: 斜率优化DP
Balloons2012
博客等级 码龄14年 9粉丝 38原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值