继续存模板。。
倍增版:
#include<stdio.h>
using namespace std;
typedef long long ll;
const int MAXN = 500000+1;
int fa[MAXN][21];int deep[MAXN];int n,m,s;
inline void swap(int &a,int &b){
int t=a;
a=b;
b=t;
}
struct node{
int v,nxt;
}e[MAXN*2];int head[MAXN];int cnt=0;
inline void add(int u,int v){e[++cnt].v = v;e[cnt].nxt = head[u];head[u] = cnt;}
inline void bfs(int s,int dad){
deep[s]=deep[dad]+1;
fa[s][0]=dad;
for(ll i=1;(1<<i)<=deep[s];++i){
fa[s][i] = fa[fa[s][i-1]][i-1];
}
for(ll i=head[s];i;i=e[i].nxt){
if(e[i].v ^ dad) bfs(e[i].v , s);
}
}
inline int lca(int x,int y){
ll i , j;
if(deep[x] < deep[y]) swap(x,y);
for(i = 0 ;(1<<i) <= deep[x] ;++i);
i--;
for(j=i;j>=0;--j)
if(deep[x] - (1<<j) >= deep[y]) x = fa[x][j];
if(x == y) return x;
for(j=i;j>=0;--j){
if(fa[x][j] ^ fa[y][j]){
x = fa[x][j];y=fa[y][j];
}
}
return fa[x][0];
}
int main(){
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=n-1;++i){
int x,y;scanf("%d%d",&x,&y);add(x,y);add(y,x);
}
bfs(s,0);
for(int i=1;i<=m;++i){
int x,y;scanf("%d%d",&x,&y);
printf("%d
",lca(x,y));
}
// for(int i=1;i<=n;++i) printf("%d ",deep[i]);
return 0;
}
tarjan版:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 500000+10;
struct node1{
int to,next;
int lca;
};
node1 e[MAXN*2];
node1 query[MAXN*2];
int cnt1=0,cnt2=0;
int head1[MAXN];
int head2[MAXN];
int fa[MAXN];
bool vis[MAXN];
inline void addedge(int u,int v){
cnt1++;
e[cnt1].to = v;
e[cnt1].next = head1[u];
head1[u] = cnt1;
}
inline void addquery(int u,int v){
cnt2++;
query[cnt2].to = v;
query[cnt2].next = head2[u];
head2[u] = cnt2;
}
int find(int x){
return x == fa[x]?x:fa[x] = find(fa[x]);
}
void tarjan(int x){
fa[x] = x;
vis[x] = 1;
for(int i=head1[x];i;i=e[i].next){
if(!vis[e[i].to]){
tarjan(e[i].to);
fa[e[i].to] = x;
}
}
for(int i=head2[x];i;i=query[i].next){
if(vis[query[i].to]){
query[i].lca = find(query[i].to);
if(i%2)
query[i+1].lca=query[i].lca;
else
query[i-1].lca=query[i].lca;
}
}
}
int main(){
int n,q,root;
scanf("%d%d%d",&n,&q,&root);
for(int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
for(int i=1;i<=q;++i){
int u,v;
scanf("%d%d",&u,&v);
addquery(u,v);
addquery(v,u);
}
tarjan(root);
for(int i=1;i<=q;++i){
printf("%d
",query[i*2].lca);
}
return 0;
}
RMQ版:
#include<bits/stdc++.h>
using namespace std;
const int M=500005;
struct node{
int to,next;
}e[M<<1];
int k=0,head[M<<1];
void add(int u,int v)
{
e[++k].to=v;
e[k].next=head[u];
head[u]=k;
}
bool vis[M];
int cnt,n,m,s,first[M],d[M<<1],pos[M<<1],f[M<<1][21];
void RMQ()
{
for(int i=1;i<=cnt;++i) f[i][0]=i;
for(int j=1;j<=20;++j)
for(int i=1;i+(1<<j)-1<=cnt;++i)
if(d[f[i][j-1]]<d[f[i+(1<<j-1)][j-1]])
f[i][j]=f[i][j-1];
else
f[i][j]=f[i+(1<<(j-1))][j-1];
}
int find(int l,int r)
{
int fl=first[l],fr=first[r];
if(fl>fr) swap(fl,fr);
int x=log(fr-fl+1.0)/log(2.0);
if(d[f[fl][x]]<d[f[fr-(1<<x)+1][x]])
return pos[f[fl][x]];
else
return pos[f[fr-(1<<x)+1][x]];
}
void dfs(int u,int deep)
{
vis[u]=1;
pos[++cnt]=u;
d[cnt]=deep;
first[u]=cnt;
for(int i=head[u];i^(-1);i=e[i].next)
if(!vis[e[i].to]){
dfs(e[i].to,deep+1);
d[++cnt]=deep;
pos[cnt]=u;
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
memset(head,-1,sizeof head);
for(int i=1;i<n;++i)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
dfs(s,1);
RMQ();
for(int i=1;i<=m;++i)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d
",find(a,b));
}
}
树链剖分 & 线段树版:
#include <cstdio>
#define N 100005
#define LL long long
#define Rei register int
inline int read(){
int _=0;char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')_=_*10+c-48,c=getchar();return _;
}
namespace Segement_Tree{
#define tl (id<<1)
#define tr (id<<1|1)
#define mid (l+r>>1)
#define lson tl,l,mid
#define rson tr,mid+1,r
LL sum[N<<2],lazy[N<<2];
inline void pushup(int id){sum[id]=sum[tl]+sum[tr];}
inline void build(int id,int l,int r){
if(l==r){sum[id]=read();return;}
build(lson);build(rson);pushup(id);
}
inline void pushdown(int id,int l,int r){
if(!lazy[id]) return ;
int ls=tl,rs=tr;
lazy[ls]+=lazy[id];
lazy[rs]+=lazy[id];
sum[rs]+=lazy[id]*(r-mid);
sum[ls]+=lazy[id]*(mid-l+1);
lazy[id]=0;return ;
}
inline void update(int id,int l,int r,int ll,int rr,LL v){
if(ll<=l&&r<=rr){
sum[id]+=(r-l+1)*v;
lazy[id]+=v;return;
}
pushdown(id,l,r);
if(rr<=mid)update(lson,ll,rr,v);
else if(ll>mid)update(rson,ll,rr,v);
else update(lson,ll,rr,v),update(rson,ll,rr,v);
pushup(id);
}
inline LL Query(int id,int l,int r,int ll,int rr){
if(ll<=l&&r<=rr)return sum[id];
pushdown(id,l,r);
if(rr<=mid)return Query(lson,ll,rr);
else if(ll>mid)return Query(rson,ll,rr);
else return Query(lson,ll,rr)+Query(rson,ll,rr);
}
#undef tl
#undef tr
#undef mid
#undef lson
#undef rson
}
using Segement_Tree::build;
using Segement_Tree::Query;
using Segement_Tree::update;
struct edge{
int to,nxt;
}e[N<<1];
int tot,head[N];
inline void addedge(const Rei&u,const Rei&v){
e[++tot].to=v;e[tot].nxt=head[u];head[u]=tot;
e[++tot].to=u;e[tot].nxt=head[v];head[v]=tot;
}
namespace Tree_pow{
int top[N],tpos[N],cnt;
int sz[N],wson[N],fa[N],dep[N];
inline void dfs(const Rei&u){
tpos[u]=++cnt;top[u]=u;sz[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa[u])continue;
dep[v]=dep[fa[v]=u]+1;
dfs(v);u;sz[u]+=sz[v];
if(sz[v]>sz[wson[u]])wson[u]=v;
}
if(wson[u]) top[wson[u]]=u;
}
inline int find(Rei x){return x==top[x]?x:top[x]=find(top[x]);}
inline int LCA(Rei x,Rei y){
while(find(x)!=find(y))
dep[top[x]]<dep[top[y]]
?y=fa[top[y]]:x=fa[top[x]];
return dep[x]<dep[y]?x:y;
}
}
using Tree_pow::dfs;
using Tree_pow::LCA;
int main(){;}