Topic links: codeforces - Company E.
We note that a sequence of LCA, which can only be dfs sequence order of the largest and smallest of the LCA, and then remove the point, can only be the largest order dfs, dfs and minimal, violence can be judged.
Key: a sequence of LCA, which can only be dfs sequence order of the largest and smallest of LCA
Segment tree maintenance interval max, min.
AC Code:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10;
int n,q;
int in[N],out[N],cnt,dfn[N];
int h[N],f[N][20],lg[N];
int mx[N<<2],mi[N<<2];
vector<int> g[N];
void dfs(int x,int fa){
h[x]=h[fa]+1; f[x][0]=fa; in[x]=++cnt; dfn[cnt]=x;
for(int i=1;(1<<i)<=h[x];i++) f[x][i]=f[f[x][i-1]][i-1];
for(auto to:g[x]) dfs(to,x); out[x]=cnt;
}
void build(int p,int l,int r){
if(l==r){mx[p]=mi[p]=in[l]; return ;}
int mid=l+r>>1;
build(p<<1,l,mid); build(p<<1|1,mid+1,r);
mx[p]=max(mx[p<<1],mx[p<<1|1]);
mi[p]=min(mi[p<<1],mi[p<<1|1]);
}
int askmax(int p,int l,int r,int ql,int qr){
if(l==ql&&r==qr) return mx[p];
int mid=l+r>>1;
if(qr<=mid) return askmax(p<<1,l,mid,ql,qr);
else if(ql>mid) return askmax(p<<1|1,mid+1,r,ql,qr);
else return max(askmax(p<<1,l,mid,ql,mid),askmax(p<<1|1,mid+1,r,mid+1,qr));
}
int askmin(int p,int l,int r,int ql,int qr){
if(l==ql&&r==qr) return mi[p];
int mid=l+r>>1;
if(qr<=mid) return askmin(p<<1,l,mid,ql,qr);
else if(ql>mid) return askmin(p<<1|1,mid+1,r,ql,qr);
else return min(askmin(p<<1,l,mid,ql,mid),askmin(p<<1|1,mid+1,r,mid+1,qr));
}
inline int lca(int x,int y){
if(h[x]<h[y]) swap(x,y);
while(h[x]>h[y]) x=f[x][lg[h[x]-h[y]]-1];
if(x==y) return x;
for(int i=lg[h[x]]-1;i>=0;i--)
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
inline int getlca(int l,int r){
if(l>r) return -1;
return lca(dfn[askmin(1,1,n,l,r)],dfn[askmax(1,1,n,l,r)]);
}
inline int get(int l,int r,int x){
int a=getlca(l,x-1),b=getlca(x+1,r);
if(a==-1||b==-1) return a+b+1;
return lca(a,b);
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>q;
for(int i=2,x;i<=n;i++) cin>>x,g[x].push_back(i);
for(int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
dfs(1,1); build(1,1,n);
while(q--){
int l,r,p; cin>>l>>r;
int u=dfn[askmin(1,1,n,l,r)],v=dfn[askmax(1,1,n,l,r)];
int c=lca(u,v),a=get(l,r,u),b=get(l,r,v);
int mx=max(h[c],max(h[a],h[b]));
if(mx==h[c]) p=l;
else if(mx==h[a]) p=u;
else p=v;
cout<<p<<' '<<mx-1<<'\n';
}
return 0;
}