Topic link: click to view
The main idea of the topic: give a rooted tree composed of n points, and then give m queries, each query needs to answer the lca of point x and point y
Problem analysis: Today I learned two very interesting methods for LCA. Summarize the pros and cons of the four methods. Refer to my own for the complexity of the implementation. If there is a code boss who can close his eyes and write casually, just ignore it. Orz
Multiplying the tree for LCA:
- time complexity:
- Preprocessing: O( nlogn)
- Query: O( logn)
- Space complexity: O( nlogn)
- Implementation complexity: the simplest
Find LCA for tree chain division:
- time complexity:
- Preprocessing: O( n)
- Query: O( logn)
- Space complexity: O(logn)
- Implementation complexity: the most difficult to write
RMQ asks for LCA:
- time complexity:
- Preprocessing: O( nlogn)
- Query: O( 1)
- Space complexity: O( nlogn)
- Implementation complexity: relatively simple
Tarjan asks for LCA (offline):
- Time complexity: O( n)
- Space complexity: O( n)
- Implementation complexity: relatively simple
In general, the current mainstream of LCA is tree multiplication and tree chain division. The tree multiplication is the simplest to achieve, the tree chain division constant is the smallest, and some problems will get stuck in the log, so sometimes Tarjan is also used offline. Please, as for RMQ, I don’t know when to use it. .
Code:
Tarjan:
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=1e6+100;
vector<pair<int,int>>qu[N];
vector<int>node[N];
int fa[N],ans[N];
bool vis[N];
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void tarjan(int u,int f)
{
fa[u]=u;
for(auto v:node[u])
{
if(v==f)
continue;
tarjan(v,u);
fa[v]=u;
}
vis[u]=true;
for(auto it:qu[u])
{
int v=it.first,id=it.second;
if(vis[v])
ans[id]=find(v);
}
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int n,m,root;
scanf("%d%d%d",&n,&m,&root);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
node[u].push_back(v);
node[v].push_back(u);
}
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
qu[u].emplace_back(v,i);
qu[v].emplace_back(u,i);
}
tarjan(root,-1);
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}
RMQ:
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=1e6+100;
vector<int>node[N];
int dfn[N],id[N][25],deep[N],cnt,lg2[N];
void dfs(int u,int fa,int dep)
{
deep[u]=dep;
dfn[u]=++cnt;
id[cnt][0]=u;
for(auto v:node[u])
{
if(v==fa)
continue;
dfs(v,u,dep+1);
id[++cnt][0]=u;
}
}
void RMQ()
{
for(int i=2;i<=cnt;i++)
lg2[i]=lg2[i>>1]+1;
for(int j=1;j<=20;j++)
for(int i=1;(i+(1<<j)-1)<=cnt;i++)
{
int l=i,r=i+(1<<(j-1));
id[i][j]=deep[id[l][j-1]]<deep[id[r][j-1]]?id[l][j-1]:id[r][j-1];
}
}
int query(int x,int y)
{
int l=dfn[x],r=dfn[y];
if(l>r)
swap(l,r);
int k=lg2[r-l+1];
return deep[id[l][k]]<deep[id[r-(1<<k)+1][k]]?id[l][k]:id[r-(1<<k)+1][k];
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int n,m,root;
scanf("%d%d%d",&n,&m,&root);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
node[u].push_back(v);
node[v].push_back(u);
}
dfs(root,0,0);
RMQ();
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",query(x,y));
}
return 0;
}