LCA 倍增||树链剖分

时间:2022-10-14 06:25:03

方法1:倍增

1498ms

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=5e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,q,root,a,b;
struct edge{
int v,ne;
}e[N<<];
int cnt=,h[N];
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int fa[N][],deep[N],vis[N];
void dfs(int u){
vis[u]=;
for(int j=;(<<j)<=deep[u];j++)
fa[u][j]=fa[fa[u][j-]][j-];
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(vis[v]) continue;
deep[v]=deep[u]+;
fa[v][]=u;
dfs(v);
}
}
int lca(int x,int y){
if(deep[x]<deep[y]) swap(x,y);
int bin=deep[x]-deep[y];
for(int i=;i<=;i++)
if((<<i)&bin) x=fa[x][i];//,printf("x %d\n",i); for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
if(x==y) return x;
else return fa[x][];
}
int main(int argc, const char * argv[]) {
n=read();q=read();root=read();
for(int i=;i<=n-;i++) a=read(),b=read(),ins(a,b);
dfs(root);
for(int i=;i<=q;i++){
a=read();b=read();
printf("%d\n",lca(a,b));
}
return ;
}

方法2:树链剖分

1314ms

让链首深度大的走到重链的父节点直到在一条重链上,返回深度小的节点

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=5e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,q,root,a,b;
struct edge{
int v,ne;
}e[N<<];
int cnt=,h[N];
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int fa[N],deep[N],mx[N],size[N];
void dfs(int u){
size[u]++;
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(v==fa[u]) continue;
fa[v]=u;deep[v]=deep[u]+;
dfs(v);
size[u]+=size[v];
if(size[v]>size[mx[u]]) mx[u]=v;
}
}
int tid[N],top[N],tot;
void dfs(int u,int anc){
if(!u) return;
tid[u]=++tot;top[u]=anc;
dfs(mx[u],anc);
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(v!=fa[u]&&v!=mx[u]) dfs(v,v);
}
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
return x;
}
int main(int argc, const char * argv[]) {
n=read();q=read();root=read();
for(int i=;i<=n-;i++) a=read(),b=read(),ins(a,b);
dfs(root);
dfs(root,root);
for(int i=;i<=q;i++){
a=read();b=read();
printf("%d\n",lca(a,b));
}
return ;
}