http://codeforces.com/problemset/problem/1062/E
[l,r]内决定lca的肯定是dfs序最小和最大的两个点 因为一棵子树的dfs序是连续的 线段树维护一下每个点dfs序的最大次大和最小次小即可 看删最小合适还是删最大合适
比赛时水题切的太慢了 根本没看见这个题 菜的一批
using namespace std;
const int maxn=1e5+10;
const int N=0x3f3f3f3f;
struct node
{
int v,next;
};
node edge[2*maxn];
int dp[maxn][20];
int maxx[4*maxn],idmax[4*maxn],minn[4*maxn],idmin[4*maxn];
int first[maxn],deep[maxn],mp[maxn];
int n,q,num;
void addedge(int u,int v)
{
edge[num].v=v;
edge[num].next=first[u];
first[u]=num++;
}
void dfs(int cur,int fa)
{
int i,v;
mp[cur]=++num;
for(i=first[cur];i!=-1;i=edge[i].next){
v=edge[i].v;
if(v!=fa){
dp[v][0]=cur,deep[v]=deep[cur]+1;
dfs(v,cur);
}
}
}
void solve()
{
int i,j;
dp[1][0]=0,deep[1]=0;
dfs(1,0);
for(j=1;(1<<j)<=n;j++){
for(i=1;i<=n;i++){
dp[i][j]=dp[dp[i][j-1]][j-1];
}
}
}
int getlca(int u,int v)
{
int i;
if(deep[u]<deep[v]) swap(u,v);
for(i=log2(n);i>=0;i--){
if(deep[dp[u][i]]>=deep[v]) u=dp[u][i];
}
if(u==v) return u;
for(i=log2(n);i>=0;i--){
if(dp[u][i]!=dp[v][i]) u=dp[u][i],v=dp[v][i];
}
return dp[u][0];
}
void pushup(int cur)
{
if(maxx[2*cur]>maxx[2*cur+1]){
maxx[cur]=maxx[2*cur];
idmax[cur]=idmax[2*cur];
}
else{
maxx[cur]=maxx[2*cur+1];
idmax[cur]=idmax[2*cur+1];
}
if(minn[2*cur]<minn[2*cur+1]){
minn[cur]=minn[2*cur];
idmin[cur]=idmin[2*cur];
}
else{
minn[cur]=minn[2*cur+1];
idmin[cur]=idmin[2*cur+1];
}
}
void build(int l,int r,int cur)
{
int m;
if(l==r){
maxx[cur]=minn[cur]=mp[l];
idmax[cur]=idmin[cur]=l;
return;
}
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
pushup(cur);
}
void update(int tar,int val,int l,int r,int cur)
{
int m;
if(l==r){
maxx[cur]=minn[cur]=val;
return;
}
m=(l+r)/2;
if(tar<=m) update(tar,val,l,m,2*cur);
else update(tar,val,m+1,r,2*cur+1);
pushup(cur);
}
void query(int tp,int &res,int &val,int pl,int pr,int l,int r,int cur)
{
int m;
if(pl<=l&&r<=pr){
if(tp==0){
if(val>minn[cur]){
val=minn[cur];
res=idmin[cur];
}
}
else{
if(val<maxx[cur]){
val=maxx[cur];
res=idmax[cur];
}
}
return;
}
m=(l+r)/2;
if(pl<=m) query(tp,res,val,pl,pr,l,m,2*cur);
if(pr>m) query(tp,res,val,pl,pr,m+1,r,2*cur+1);
}
int main()
{
int i,l,r,u,v,p,val,res,ans1,ans2;
scanf("%d%d",&n,&q);
memset(first,-1,sizeof(first));
num=0;
for(i=2;i<=n;i++){
scanf("%d",&p);
addedge(p,i),addedge(i,p);
}
num=0;
solve();
build(1,n,1);
while(q--){
scanf("%d%d",&l,&r);
ans2=-1;
val=N;
query(0,u,val,l,r,1,n,1);//minn
val=-N;
query(1,p,val,l,r,1,n,1);
update(p,-N,1,n,1);
val=-N;
query(1,v,val,l,r,1,n,1);//cmaxx
update(p,mp[p],1,n,1);
res=deep[getlca(u,v)];
if(ans2<res){
ans1=p,ans2=res;
}
val=-N;
query(1,u,val,l,r,1,n,1);//maxx
val=N;
query(0,p,val,l,r,1,n,1);
update(p,N,1,n,1);
val=N;
query(0,v,val,l,r,1,n,1);//cminn
update(p,mp[p],1,n,1);
res=deep[getlca(u,v)];
if(ans2<res){
ans1=p,ans2=res;
}
printf("%d %d\n",ans1,ans2);
}
return 0;
}
/*
6 2
1 2 1 2 4
2 3
1 4
*/