RMQ与LCA问题

一、RMQ问题  Range Maximum/Minimum Query 区间最值查询

  1. 问题描述:给定一个数组A,回答询问RMQ(a, i, j),即a[i...j]之间的最值的下标。
  2. 最简单的算法是O(n)的,但是对于查询次数很多(如100万次),O(n)的算法效率不够。解决这个的问题的一种算法是线段树算法(在线段树中保存线段的最值),复杂度为Ologn)。不过,最好的算法是Sparse TableST)算法,它可以在O(nlogn)的预处理以后,实现O(1)的查询。
  3. ST算法(以查询最小值为例)
  • 第一步:预处理

预处理使用DP(动态规划)的思想。f(i, j)表示[i, i+2^j - 1]区间中的最小值。例如,f(0, 0)表示[0,0]之间的最小值,就是a[0], f(0, 2)表示[0, 3]之间的最小值, f(2, 4)表示[2, 17]之间的最小值。采用自底而上的方法构造数组f(i, j),递推关系式为:

f(i, 0) = a[i]

f(i, j) = min( f(i,j - 1), f(i+2^(j-1), j-1))

  • 第二步:查询

假设要查询从mn这一段的最小值,那么我们先求出一个最大的k,使得k满足2^k <= (n - m + 1)。于是我们就可以把[m, n]分成两个长度为2^k的区间: [m,m+2^k-1], [n-2^k+1, n](有部分重叠);而我们之前已经求出了f(m, k)[m, m+2^k-1]的最小值, f(n-2^k+1, k)[n-2^k+1,n]的最小值我们只要返回其中更小的那个,就是我们想要的答案,这个算法的时间复杂度是O(1)

例如, RMQ(0, 11) = min(f(0, 3), f(4, 3))

 

二、LCA问题  Lowest Common Ancestor 最低公共祖先

 

  1. 问题描述:对于一棵有根树T的任意两个节点uv,求出LCA(T, u, v),即离根最远的节点x,使得x同时是uv的祖先。

在线算法:用比较长的时间做预处理,但是等信息充足以后每次回答询问只需要用比较少的时间

离线算法:先把所有的询问读入,然后一起回答所有的询问

    

  1. 算法一:Tarjan算法(离线算法)

一次读入所有LCA询问,然后回答。Tarjan算法是通过并查集和DFS结合实现的,其伪代码为:
LCA(u)   
{   
     Make-Set(u)   
     ancestor[Find(u)]=u   
    
对于u的每一个孩子v   
     {   
         LCA(v)   
         Union(u)   
         ancestor[Find(u)]=u   
     }   
     checked[u]=true  
    
对于每个(u,v)属于P    /* P存储所有的LCA询问 */
     {   
         if checked[v]=true  
        then {   
            
回答uv的最近公共祖先为 ancestor[Find(v)]   
         }   
     }   

其中,makest就是建立一个集合,makesetu)就是建立一个只含U的集合。

并查集是一种处理元素之间等价关系的数据结构,一开始我们假设每个元素都是分别属于一个独立的集合,主要有两种操作:

合并两个不相交集合(Union)

查询元素所属的集合,返回根节点,根节点代表这个集合(Find)

 

  1. 算法二:转化为RMQ问题

 

1)       DFS:从树T的根开始,进行深度优先遍历,并记录下每次到达的顶点。第一个的结点是root(T),每经过一条边都记录它的端点。由于每条边恰好经过2次,因此一共记录了2n-1个结点,用E[1, ... , 2n-1]来表示。

2)       计算R:用R[i]表示E数组中第一个值为i的元素下标,即如果R[u] < R[v]时,DFS访问的顺序是E[R[u], R[u]+1, ..., R[v]]。虽然其中包含u的后代,但深度最小的还是uv的公共祖先。

3)       RMQ:当R[u] R[v]时,LCA[T, u, v] = RMQ(E, R[v], R[u]);否则LCA[T, u, v] = RMQ(E, R[u], R[v]),计算RMQ

由于RMQ使用的ST算法是在线算法,所以这个算法也是在线算法。

 

如图,DFS遍历得到的数组E[1,…,9]为:

1

2

3

4

5

6

7

8

9

1

2

4

2

5

2

1

3

1

数组R[1,…,5]为:

1

2

3

4

5

1

2

8

3

5

 

例:LCA[T, 3, 4] = RMQ(E, R[4], R[3]) = RMQ[E, 3, 8] = E[7] = 1

LCA[T, 4, 5] = RMQ(E, R[4], R[5]) = RMQ[E, 3, 5] = E[4] = 2


另见文章http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值