Company题解

Company题解

我们按照普遍规律可以知道感性理解
对于一群点,我们可以删去一个点,要使其公共LCA深度最大,只会删除dfs序最左边或dfs序最右边的点。
所以不就很好搞了吗。
两种操作选其一即可:

#include<bits/stdc++.h>
#define lc x<<1
#define rc x<<1|1
using namespace std;
const int N=1e5+7;
int n,q,t,t1,t2,lf,rg,LCA,LCA2,cnt=0,num=0,ansl,ansr,d[N],dfn[N],rev[N],head[N],Min[N<<2],Max[N<<2],f[N][21];
struct edge{int nxt,to;}e[N];
inline void add(int u,int v){e[++cnt].nxt=head[u],e[cnt].to=v,head[u]=cnt;}
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
void dfs(int x,int fa){
    d[x]=d[fa]+1,f[x][0]=fa,dfn[x]=++num,rev[num]=x;
    for(int i=1;i<=18;++i) f[x][i]=f[f[x][i-1]][i-1];
    for(int i=head[x];i;i=e[i].nxt) dfs(e[i].to,x);
}
void build(int l,int r,int x){
    if(l==r){Min[x]=Max[x]=dfn[l]; return;}
    int mid=l+r>>1;
    build(l,mid,lc),build(mid+1,r,rc);
    Max[x]=max(Max[lc],Max[rc]),Min[x]=min(Min[lc],Min[rc]);
}
int query(int l,int r,int p,int q,int x){
   if(p>q) return n+1;
   if(p<=l&&r<=q) return Min[x];
   int mid=l+r>>1,ans=n+1;
   if(p<=mid) ans=min(ans,query(l,mid,p,q,lc));
   if(q>mid) ans=min(ans,query(mid+1,r,p,q,rc));
   return ans;
}
int query2(int l,int r,int p,int q,int x){
   if(p>q) return 0;
   if(p<=l&&r<=q) return Max[x];
   int mid=l+r>>1,ans=0;
   if(p<=mid) ans=max(ans,query2(l,mid,p,q,lc));
   if(q>mid) ans=max(ans,query2(mid+1,r,p,q,rc));
   return ans;
}
int lca(int x,int y){
   if(d[x]<d[y]) swap(x,y);
   for(int i=18;i>=0;--i) if(d[x]>=d[y]+(1<<i)) x=f[x][i];
   if(x==y) return x;
   for(int i=18;i>=0;--i) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
   return f[x][0]; 
}
int main(){
   n=read(),q=read();
   for(int i=2;i<=n;++i) t=read(),add(t,i);
   d[0]=-1,dfs(1,0),build(1,n,1);
   for(int i=1;i<=q;++i){
       t1=read(),t2=read(),lf=rev[query(1,n,t1,t2,1)],rg=rev[query2(1,n,t1,t2,1)];
       ansl=rev[min(query(1,n,t1,lf-1,1),query(1,n,lf+1,t2,1))];
       ansr=rev[max(query2(1,n,t1,rg-1,1),query2(1,n,rg+1,t2,1))];
       LCA=lca(ansl,rg),LCA2=lca(lf,ansr);
       if(d[LCA]>d[LCA2]) printf("%d %d\n",lf,d[LCA]);
       else printf("%d %d\n",rg,d[LCA2]);
   }
   return 0;
}

猜你喜欢

转载自www.cnblogs.com/ljk123-de-bo-ke/p/11789560.html