题目链接:Codeforces - E. Company
我们注意到,一个序列的LCA,只可能是序列当中dfs序最大的和最小的的LCA,然后去除的点,也只能是最大的dfs序,和最小的dfs,暴力判断即可。
重点:一个序列的LCA,只可能是序列当中dfs序最大的和最小的的LCA
线段树维护区间max,min。
AC代码:
#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;
}