1.概述
LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先)。
RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。
在线算法:指用户每输入一个查询便马上处理一个查询。该算法一般用较长的时间做预处理,待信息充足以后便可以用较少的时间回答每个查询。
离线算法:先输入所有数据,然后一起处理,一步到位
q为查询量,n为节点数
2.RMQ
O(n*q):遍历,数据量非常大且查询很频繁时不可用
在线ST:预处理时间O(nlogn),查询时间O(q)
思路:
(1)预处理:倍增,f[i][j]表示从i起2^j个数内的最值,f[i][0]即为第i个数,由此可得状态转移方程:f[i, j]=max(f[i][j-1], f[i + 2^(j-1)][j-1]).
(2)查询:对[i,j]内的最值(即RMQ[i][j]),先设k=log2(j-i+1),则有RMQ[i][j]=min{f[i,k],f[j-2^k+1,k]}
3.LCA
O(n*q):先调整高度为等高,在一起向上查询,直到两节点相同,该节点即为公共父节点
在线DFS+ST:总时间复杂O((n+1)log2n+q)
思路:
(1) 预处理:f[i][j]表示第i个节点向上的第2^j个父节点,f[i][0]即父节点,遍历一遍树,记录节点高度以及父节点(f[i][0]),然后dp,状态转移方程:f[i][j]=f[f[i][j-1]][j-1].
(2) 查询:对i,j的最近公共父节点(LCA[i][j]),先调整i,j的高度,在一起倍增向上查询,直到找到公共父节点为止
离线tarjan:总时间复杂度O(n+q)
思路:
(1)任选一个点为根节点,从根节点开始遍历
(2)遍历某点u所有子节点v,并标记这些子节点v已被访问过,若是v还有子节点,继续深搜
(3)合并v到u上(并查集)
(4)寻找与当前点u有询问关系的点v(可以预处理)
(5)若是v已经被访问过了,则可以确认u和v的最近公共祖先为fa[v]