一个性质,一群节点的lca一定是其中dfn最小的的节点和dfn最大的节点的lca
用线段树维护区间dfn的最大值和最小值即可
#include<iostream>
#include<vector>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace lst
{
struct node
{
int l,r;
pii maxx;
pii minn;
//x表示值,y表示位置
}tre[400005];
void build(int l,int r,int k)
{
tre[k].l=l;
tre[k].r=r;
if(l==r)
return;
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
}
void change(int pos,int val,int k)
{
if(tre[k].l>pos||pos>tre[k].r)
return;
if(tre[k].l==tre[k].r)
{
tre[k].maxx.x=tre[k].minn.x=val;
tre[k].maxx.y=tre[k].minn.y=tre[k].l;
return;
}
change(pos,val,k<<1);
change(pos,val,k<<1|1);
tre[k].maxx=max(tre[k<<1].maxx,tre[k<<1|1].maxx);
tre[k].minn=min(tre[k<<1].minn,tre[k<<1|1].minn);
}
pii ask_min(int l,int r,int k)
{
if(tre[k].l>r||l>tre[k].r)
return make_pair(1<<30,0);
if(l<=tre[k].l&&tre[k].r<=r)
return tre[k].minn;
return min(ask_min(l,r,k<<1),ask_min(l,r,k<<1|1));
}
pii ask_max(int l,int r,int k)
{
if(tre[k].l>r||l>tre[k].r)
return make_pair(0,0);
if(l<=tre[k].l&&tre[k].r<=r)
return tre[k].maxx;
return max(ask_max(l,r,k<<1),ask_max(l,r,k<<1|1));
}
}
using namespace lst;
int n,q,cnt;
int dfn[100005];
int dep[100005],dp[100005][25];
vector<int> g[100005];
void dfs(int u,int fa)
{
dfn[u]=++cnt;
change(u,dfn[u],1);
dep[u]=dep[fa]+1;
for(int i=1;i<=20;i++)
dp[u][i]=dp[dp[u][i-1]][i-1];
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=fa)
{
dp[v][0]=u;
dfs(v,u);
}
}
}
int lca(int u,int v)
{
if(u==v)
return u;
if(dep[u]>dep[v])
swap(u,v);
for(int i=20;i>=0;i--)
if(dep[u]<=dep[dp[v][i]])
v=dp[v][i];
if(u==v)
return u;
for(int i=20;i>=0;i--)
if(dp[u][i]!=dp[v][i])
{
u=dp[u][i];
v=dp[v][i];
}
return dp[u][0];
}
int solve(int l,int r,int cnt)
{
if(cnt==l)
{
pii t1=ask_max(l+1,r,1);
pii t2=ask_min(l+1,r,1);
return lca(t1.y,t2.y);
}
else if(cnt==r)
{
pii t1=ask_max(l,r-1,1);
pii t2=ask_min(l,r-1,1);
return lca(t1.y,t2.y);
}
else
{
pii t1=ask_max(l,cnt-1,1);
pii t2=ask_min(l,cnt-1,1);
pii s1=ask_max(cnt+1,r,1);
pii s2=ask_min(cnt+1,r,1);
return lca(lca(t1.y,t2.y),lca(s1.y,s2.y));
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>q;
build(1,n,1);
for(int i=2,u;i<=n;i++)
{
cin>>u;
g[i].push_back(u);
g[u].push_back(i);
}
dep[0]=-1;
dfs(1,0);
for(int i=1,l,r;i<=q;i++)
{
cin>>l>>r;
pii t1=ask_max(l,r,1),t2=ask_min(l,r,1);
int lca1=solve(l,r,t1.y),lca2=solve(l,r,t2.y);
if(dep[lca1]>dep[lca2])
cout<<t1.y<<' '<<dep[lca1]<<'\n';
else
cout<<t2.y<<' '<<dep[lca2]<<'\n';
}
return 0;
}