B - pog loves szh III (在线倍增LCA)
Pog and Szh are playing games. Firstly Pog draw a tree on the paper. Here we define 1 as the root of the tree.
Then Szh choose some nodes from the tree. He wants Pog helps to find the least common ancestor (LCA) of these node.
The question is too difficult for Pog.So he decided to simplify the problems.The nodes picked are consecutive numbers
from li to ri ([li,ri]) Hint : You should be careful about stack overflow !
Input
Several groups of data (no more than 3 groups,n≥10000n≥10000 or Q≥10000Q≥10000).
The following line contains ans integers,n(2≤n≤300000)n(2≤n≤300000).
AT The following n−1n−1 line, two integers are bibi and cici at every line, it shows an edge connecting bibi and cici.
The following line contains ans integers,Q(Q≤300000)Q(Q≤300000).
AT The following QQ line contains two integers li and ri(1≤li≤ri≤n1≤li≤ri≤n).
Output
For each case,output QQ integers means the LCA of [li,ri][li,ri].
Sample Input
5
1 2
1 3
3 4
4 5
5
1 2
2 3
3 4
3 5
1 5
Sample Output
1
1
3
3
1
大意思路:
题意: 找到区间节点的最小共同祖先(LCA)
思路:
fa[i][j]=fa[fa[i][j-1]][j-1];找到所有点父节点
在倍增LCA(ST算法)
代码实现:
点击查看代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstdio>
using namespace std ;
typedef long long LL ;
const int N = 400030 ;
const int DEG = 30 ;
int n;
struct Edge{
int to,next;
}edge[N*2];
int head[N],tot;
void addedge(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void init(){
tot = 0;
memset(head,-1,sizeof(head));
}
int fa[N][DEG] , deg[N];
void DFS(int u) {
for(int i=head[u]; i!=-1; i=edge[i].next) {
int to=edge[i].to;
if(to==fa[u][0])
continue;
deg[to]=deg[u]+1;//深度加一
fa[to][0]=u; //p[i][0]存i的父节点
DFS(to);
}
}
void F()//i的2^j祖先就是i的(2^(j-1))祖先的2^(j-1)祖先
{
for(int j=1; (1<<j)<=n; j++)
for(int i=1; i<=n; i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
int LCA(int u,int v)
{
if(deg[u] > deg[v])swap(u,v);
int hu = deg[u], hv = deg[v];
int tu = u, tv = v;
int det = hv-hu;
for( int i = 0 ;(1<<i)<=det;i++)//(1<<i)&f找到f化为2进制后1的位置,移动到相应的位置
if((1<<i)&det) //比如f=5,二进制
tv = fa[tv][i];
if(tu == tv)return tu;
for(int i = DEG-1; i >= 0; i--) //从最大祖先开始,判断a,b祖先,是否相同
{
if(fa[tu][i] == fa[tv][i])
continue;
tu = fa[tu][i]; //如不相同,a b同时向上移动2^j
tv = fa[tv][i];
}
return fa[tu][0]; //这时a的father就是LCA
}
int main()
{
while( ~scanf("%d",&n) ) {
init();
for( int i = 1 ; i < n ; ++i ) {
int u , v ; scanf("%d%d",&u,&v);
addedge( u , v ) ;
addedge( v , u ) ;
}
DFS(1);
F();
int q ; scanf("%d",&q);
while( q-- ) {
int x , y ; scanf("%d%d",&x,&y);
printf("%d\n",LCA(x,y));
}
}
return 0;
}
LCA算法理解学习见:
LCA算法 - Palpitate` - 博客园 (cnblogs.com)

浙公网安备 33010602011771号