#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
int read()
{
	char ch=getchar();int h=0,t=1;
	while((ch>'9'||ch<'0')&&ch!='-') ch=getchar();
	if(ch=='-') t=-1,ch=getchar();
	while(ch>='0'&&ch<='9') h=h*10+ch-'0',ch=getchar();
	return h*t;
}
const int N=401000;
struct edge{int next,to;}a[N<<1];
struct Que{int x,st,id,T;}A[N];
int n,m,head[N],cnt,dep[N],dfn[N],top[N],id[N],fa[N],siz[N],son[N],tot;
int cmp1(const Que&A,const Que&B)
{
	return (A.st+dep[A.x]<B.st+dep[B.x])|
		(A.st+dep[A.x]==B.st+dep[B.x]&&A.x<B.x);
}
int cmp2(const Que&A,const Que&B) {return A.id<B.id;}
void link(int x,int y) {a[++cnt]=(edge){head[x],y};head[x]=cnt;}
void dfs1(int x)
{
	siz[x]=1;dep[x]=dep[fa[x]]+1;
	for(int i=head[x];i;i=a[i].next)
	{
		int R=a[i].to;if(R==fa[x]) continue;
		dfs1(R);siz[x]+=siz[R];
		if(siz[R]>siz[son[x]]) son[x]=R;
	}
}
void dfs2(int x)
{
	top[x]=x;dfn[x]=++tot;id[tot]=x;
	if(son[fa[x]]==x) top[x]=top[fa[x]];
	if(son[x]) dfs2(son[x]);
	for(int i=head[x];i;i=a[i].next)
		if(a[i].to!=fa[x]&&a[i].to!=son[x]) dfs2(a[i].to);
}
int t[N<<3],T[N<<3],lz[N<<3];
void Max(int &a,int b) {if(b>a) a=b;}
void Build(int now,int l,int r)
{
	if(l==r) {t[now]=2*dep[id[l]];T[now]=-1e8;return;}
	int mid=(l+r)>>1;
	Build(now<<1,l,mid);
	Build(now<<1|1,mid+1,r);
	t[now]=max(t[now<<1],t[now<<1|1]);
	T[now]=max(T[now<<1],T[now<<1|1]);
}
void put(int x,int k) {T[x]=max(T[x],t[x]+k);lz[x]=max(lz[x],k);}
void pushdown(int x)
{
	int &s=lz[x];if(!s) return;
	put(x<<1,s);put(x<<1|1,s);s=0;
}
void Cover(int now,int l,int r,int gl,int gr,int k)
{
	if(l>=gl&&r<=gr) {put(now,k);return;}
	pushdown(now);
	int mid=(l+r)>>1;
	if(gl<=mid) Cover(now<<1,l,mid,gl,gr,k);
	if(gr>mid) Cover(now<<1|1,mid+1,r,gl,gr,k);
	T[now]=max(T[now<<1],T[now<<1|1]);
}
int Query(int now,int l,int r,int gl,int gr)
{
	if(l>=gl&&r<=gr) return T[now];
	int mid=(l+r)>>1,res=0;
	pushdown(now);
	if(gl<=mid) Max(res,Query(now<<1,l,mid,gl,gr));
	if(gr>mid) Max(res,Query(now<<1|1,mid+1,r,gl,gr));
	return res;
}
int main()
{
	n=read()+1;m=read();if(!m) return 0;
	for(int i=2;i<=n;i++) fa[i]=read()+1,link(fa[i],i);
	for(int i=1,x,st;i<=m;i++) x=read()+1,st=read(),A[i]=(Que){x,st,i,-1};
	dfs1(1);dfs2(1);sort(A+1,A+m+1,cmp1);Build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		int x=A[i].x,tt=x,res=0;
		if(Query(1,1,n,dfn[x],dfn[x])>A[i].st+dep[x]) {A[i].T=A[i].st;continue;}
		while(tt)
		{
			int mx=Query(1,1,n,dfn[top[tt]],dfn[tt]);
			if(mx<=dep[x]+A[i].st) {res=top[tt],tt=fa[top[tt]];continue;}
			int l=dfn[top[tt]],r=dfn[tt];
			while(l<=r)
			{
				int mid=(l+r)>>1;
				mx=Query(1,1,n,mid,r);
				if(mx<=dep[x]+A[i].st) res=id[mid],r=mid-1;
				else l=mid+1;
			}
			break;
		}
		A[i].T=A[i].st+2*(dep[x]-dep[tt?fa[res]:1]);
		int kk=A[i].st+dep[x]-2*dep[tt?fa[res]:1];
		while(x)
		{
			Cover(1,1,n,dfn[top[x]],dfn[x],kk);
			x=fa[top[x]];
		}
	}
	sort(A+1,A+m+1,cmp2);
	for(int i=1;i<=m;i++) printf("%d ",A[i].T);
	return 0;
}


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
int read()
{
    char ch=getchar();int h=0,t=1;
    while((ch>'9'||ch<'0')&&ch!='-') ch=getchar();
    if(ch=='-') t=-1,ch=getchar();
    while(ch>='0'&&ch<='9') h=h*10+ch-'0',ch=getchar();
    return h*t;
}
const int N=201000;
struct edge{int next,to;}a[N<<1];
struct Que{int x,st,id,T;}A[N];
int n,m,head[N],cnt,dep[N],dfn[N],top[N],id[N],fa[N],siz[N],son[N],tot;
int cmp1(const Que&A,const Que&B)
{
    return (A.st+dep[A.x]<B.st+dep[B.x])|
        (A.st+dep[A.x]==B.st+dep[B.x]&&A.x<B.x);
}
int cmp2(const Que&A,const Que&B) {return A.id<B.id;}
void link(int x,int y) {a[++cnt]=(edge){head[x],y};head[x]=cnt;}
void dfs1(int x)
{
    siz[x]=1;dep[x]=dep[fa[x]]+1;
    for(int i=head[x];i;i=a[i].next)
    {
        int R=a[i].to;if(R==fa[x]) continue;
        dfs1(R);siz[x]+=siz[R];
        if(siz[R]>siz[son[x]]) son[x]=R;
    }
}
void dfs2(int x)
{
    top[x]=x;dfn[x]=++tot;id[tot]=x;
    if(son[fa[x]]==x) top[x]=top[fa[x]];
    if(son[x]) dfs2(son[x]);
    for(int i=head[x];i;i=a[i].next)
        if(a[i].to!=fa[x]&&a[i].to!=son[x]) dfs2(a[i].to);
}
int t[N<<3],T[N<<3],lz[N<<3];
void Max(int &a,int b) {if(b>a) a=b;}
void Build(int now,int l,int r)
{
	T[now]=lz[now]=-1e9;
    if(l==r) {t[now]=2*dep[id[l]];return;}
    int mid=(l+r)>>1;
    Build(now<<1,l,mid);
    Build(now<<1|1,mid+1,r);
    t[now]=max(t[now<<1],t[now<<1|1]);
}
void put(int x,int k) {T[x]=t[x]+k;lz[x]=k;}
void pushdown(int x)
{
    int &s=lz[x];if(s==-1e9) return;
    put(x<<1,s);put(x<<1|1,s);s=-1e9;
}
void Cover(int now,int l,int r,int gl,int gr,int k)
{
    if(l>=gl&&r<=gr) {put(now,k);return;}
    pushdown(now);
    int mid=(l+r)>>1;
    if(gl<=mid) Cover(now<<1,l,mid,gl,gr,k);
    if(gr>mid) Cover(now<<1|1,mid+1,r,gl,gr,k);
    T[now]=max(T[now<<1],T[now<<1|1]);
}
int Query(int now,int l,int r,int gl,int gr)
{
    if(l>=gl&&r<=gr) return T[now];
    int mid=(l+r)>>1,res=-1e9;
    pushdown(now);
    if(gl<=mid) Max(res,Query(now<<1,l,mid,gl,gr));
    if(gr>mid) Max(res,Query(now<<1|1,mid+1,r,gl,gr));
    return res;
}
int main()
{
    n=read()+1;m=read();if(!m) return 0;
    for(int i=2;i<=n;i++) fa[i]=read()+1,link(fa[i],i);
    for(int i=1,x,st;i<=m;i++) x=read()+1,st=read(),A[i]=(Que){x,st,i,-1};
    dfs1(1);dfs2(1);sort(A+1,A+m+1,cmp1);Build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int x=A[i].x,tt=x,res=0;
        if(Query(1,1,n,dfn[x],dfn[x])>A[i].st+dep[x]) {A[i].T=A[i].st;continue;}
        while(tt)
        {
            int mx=Query(1,1,n,dfn[top[tt]],dfn[tt]);
            if(mx<=dep[x]+A[i].st) {res=top[tt],tt=fa[top[tt]];continue;}
            int l=dfn[top[tt]],r=dfn[tt];
            while(l<=r)
            {
                int mid=(l+r)>>1;
                mx=Query(1,1,n,mid,r);
                if(mx<=dep[x]+A[i].st) res=id[mid],r=mid-1;
                else l=mid+1;
            }
            break;
        }
        A[i].T=A[i].st+2*(dep[x]-dep[tt?fa[res]:1]);
        int kk=A[i].st+dep[x]-2*dep[tt?fa[res]:1];
        if(tt) Cover(1,1,n,dfn[res],dfn[tt],kk);
        while(x!=tt)
        {
            Cover(1,1,n,dfn[top[x]],dfn[x],kk);
            x=fa[top[x]];
        }
    }
    sort(A+1,A+m+1,cmp2);
    for(int i=1;i<=m;i++) printf("%d ",A[i].T);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
int read()
{
	char ch=getchar();int h=0,t=1;
	while((ch>'9'||ch<'0')&&ch!='-') ch=getchar();
	if(ch=='-') t=-1,ch=getchar();
	while(ch>='0'&&ch<='9') h=h*10+ch-'0',ch=getchar();
	return h*t;
}
const int N=401000;
struct edge{int next,to;}a[N<<1];
struct Que{int x,st,id,T;}A[N];
int n,m,head[N],cnt,dep[N],dfn[N],top[N],id[N],fa[N],siz[N],son[N],tot;
int cmp1(const Que&A,const Que&B)
{
	return (A.st+dep[A.x]<B.st+dep[B.x])|
		(A.st+dep[A.x]==B.st+dep[B.x]&&A.x<B.x);
}
int cmp2(const Que&A,const Que&B) {return A.id<B.id;}
void link(int x,int y) {a[++cnt]=(edge){head[x],y};head[x]=cnt;}
void dfs1(int x)
{
	siz[x]=1;dep[x]=dep[fa[x]]+1;
	for(int i=head[x];i;i=a[i].next)
	{
		int R=a[i].to;if(R==fa[x]) continue;
		dfs1(R);siz[x]+=siz[R];
		if(siz[R]>siz[son[x]]) son[x]=R;
	}
}
void dfs2(int x)
{
	top[x]=x;dfn[x]=++tot;id[tot]=x;
	if(son[fa[x]]==x) top[x]=top[fa[x]];
	if(son[x]) dfs2(son[x]);
	for(int i=head[x];i;i=a[i].next)
		if(a[i].to!=fa[x]&&a[i].to!=son[x]) dfs2(a[i].to);
}
int t[N<<3],T[N<<3],lz[N<<3];
void Max(int &a,int b) {if(b>a) a=b;}
void Build(int now,int l,int r)
{
	T[now]=lz[now]=-1e9;
	if(l==r) {t[now]=2*dep[id[l]];return;}
	int mid=(l+r)>>1;
	Build(now<<1,l,mid);
	Build(now<<1|1,mid+1,r);
	t[now]=max(t[now<<1],t[now<<1|1]);
}
void put(int x,int k) {T[x]=max(T[x],t[x]+k);lz[x]=max(lz[x],k);}
void pushdown(int x)
{
	int &s=lz[x];if(s==-1e9) return;
	put(x<<1,s);put(x<<1|1,s);s=-1e9;
}
void Cover(int now,int l,int r,int gl,int gr,int k)
{
	if(l>=gl&&r<=gr) {put(now,k);return;}
	pushdown(now);
	int mid=(l+r)>>1;
	if(gl<=mid) Cover(now<<1,l,mid,gl,gr,k);
	if(gr>mid) Cover(now<<1|1,mid+1,r,gl,gr,k);
	T[now]=max(T[now<<1],T[now<<1|1]);
}
int Query(int now,int l,int r,int gl,int gr)
{
	if(l>=gl&&r<=gr) return T[now];
	int mid=(l+r)>>1,res=-1e9;
	pushdown(now);
	if(gl<=mid) Max(res,Query(now<<1,l,mid,gl,gr));
	if(gr>mid) Max(res,Query(now<<1|1,mid+1,r,gl,gr));
	return res;
}
int main()
{
	n=read()+1;m=read();if(!m) return 0;
	for(int i=2;i<=n;i++) fa[i]=read()+1,link(fa[i],i);
	for(int i=1,x,st;i<=m;i++) x=read()+1,st=read(),A[i]=(Que){x,st,i,-1};
	dfs1(1);dfs2(1);sort(A+1,A+m+1,cmp1);Build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		int x=A[i].x,tt=x,res=0;
		if(Query(1,1,n,dfn[x],dfn[x])>A[i].st+dep[x]) {A[i].T=A[i].st;continue;}
		while(tt)
		{
			int mx=Query(1,1,n,dfn[top[tt]],dfn[tt]);
			if(mx<=dep[x]+A[i].st) {res=top[tt],tt=fa[top[tt]];continue;}
			int l=dfn[top[tt]],r=dfn[tt];
			while(l<=r)
			{
				int mid=(l+r)>>1;
				mx=Query(1,1,n,mid,r);
				if(mx<=dep[x]+A[i].st) res=id[mid],r=mid-1;
				else l=mid+1;
			}
			break;
		}
		A[i].T=A[i].st+2*(dep[x]-dep[tt?fa[res]:1]);
		int kk=A[i].st+dep[x]-2*dep[tt?fa[res]:1];
		while(x)
		{
			Cover(1,1,n,dfn[top[x]],dfn[x],kk);
			x=fa[top[x]];
		}
	}
	sort(A+1,A+m+1,cmp2);
	for(int i=1;i<=m;i++) printf("%d ",A[i].T);
	return 0;
}


#include <cstdio>
#include <cassert>
#include <cstring>
#include <algorithm>
#define meow(args...) fprintf(stderr, args)

struct Query {int x, t, *ans;};
struct Segment {int l, r, max, tid;};

const int N=2e5+1;

int n, m, p[N], prefer[N], size[N], dep[N], dfn[N], top[N], ans[N];
Query q[N];
Segment seg[1<<19];
std::vector<int> ch[N], dfo, tag;

template<class T1, class T2> inline bool cmin(T1 &a, const T2 &b) {return b<a?(a=b, true):false;}
template<class T1, class T2> inline bool cmax(T1 &a, const T2 &b) {return a<b?(a=b, true):false;}
template<class Type> Type read() {
	Type a;
	bool b;
	unsigned char c;
	while(c=getchar(), c-'0'>9&c!='-');
	for(a=(b=c=='-')?0:c-'0'; (c=getchar()-'0')<=9; a=a*10+c);
	return b?-a:a;
}

void dfs_init(int x, int d) {
	int max=0;
	dep[x]=d;
	size[x]=1;
	for(int i: ch[x]) {
		dfs_init(i, d+1);
		if(cmax(max, size[i])) prefer[x]=i;
		size[x]+=size[i];
	}
}
void dfs_make(int x, int t) {
	top[x]=t;
	dfn[x]=dfo.size();
	dfo.push_back(x);
	if(prefer[x]) dfs_make(prefer[x], t);
	for(int i: ch[x]) if(i!=prefer[x]) dfs_make(i, i);
}

void build(int i, int l, int r) {
	seg[i]=(Segment){l, r, 0, -1};
	if(l!=r) {
		int mid=(l+r)/2;
		build(i<<1, l, mid);
		build(i<<1|1, mid+1, r);
	}
}
void do_cover(int i, int t) {
	if(cmax(seg[i].tid, t)) seg[i].max=tag[t]+2*dep[dfo[seg[i].r]];
}
void pushdown(int i) {
	if(seg[i].tid!=-1) {
		do_cover(i<<1, seg[i].tid);
		do_cover(i<<1|1, seg[i].tid);
		seg[i].tid=-1;
	}
}
int find_last_greater(int i, int qr, int qv) {
	if(qr<seg[i].l||seg[i].max<=qv) return -1;
	if(seg[i].l==seg[i].r) return seg[i].l;
	pushdown(i);
	int rans=find_last_greater(i<<1|1, qr, qv);
	return rans==-1?find_last_greater(i<<1, qr, qv):rans;
}
void cover(int i, int ql, int qr, int qv) {
	if(ql>seg[i].r||qr<seg[i].l) return;
	if(ql<=seg[i].l&&seg[i].r<=qr) return do_cover(i, qv);
	pushdown(i);
	cover(i<<1, ql, qr, qv);
	cover(i<<1|1, ql, qr, qv);
	seg[i].max=std::max(seg[i<<1].max, seg[i<<1|1].max);
}
int main() {
	int (*rd)()=read<int>;
	n=rd(), m=rd();
	for(int i=1; i<=n; ++i) ch[p[i]=rd()].push_back(i);
	dfs_init(0, 0);
	dfs_make(0, 0);
	for(int i=0; i<m; ++i) {
		int x=rd(), t=dep[x]+rd();
		q[i]=(Query){x, t, ans+i};
	}
	std::sort(q, q+m, [](const Query &a, const Query &b) {return a.t<b.t||a.t==b.t&&a.x<b.x;});
	build(1, 0, n);
	for(int i=0; i<m; ++i) {
		int x, v;
		for(x=q[i].x; x; x=p[top[x]]) {
			v=find_last_greater(1, dfn[x], q[i].t);
			if(v>=dfn[top[x]]) break;
		}
		if(x==0) v=0; else v=dfo[v];
		int vtick=q[i].t-dep[v];
		*q[i].ans=vtick+dep[q[i].x]-dep[v];
		for(x=q[i].x; top[x]!=top[v]; x=p[top[x]]) {
			tag.push_back(vtick-dep[v]);
			cover(1, dfn[top[x]], dfn[x], tag.size()-1);
		}
		if(v!=x) {
			tag.push_back(vtick-dep[v]);
			cover(1, dfn[v]+1, dfn[x], tag.size()-1);
		}
	}
	for(int i=0; i<m; ++i) printf("%d ", ans[i]);
	puts("");
	return 0;
}


#include <cstdio>
#include <cassert>
#include <cstring>
#include <algorithm>
#define meow(args...) fprintf(stderr, args)

struct Query {int x, t, *ans;};
struct Segment {int l, r, max, tid;};

const int N=2e5+1;

int n, m, p[N], prefer[N], size[N], dep[N], dfn[N], top[N], ans[N];
Query q[N];
Segment seg[N];
std::vector<int> ch[N], dfo, tag;

template<class T1, class T2> inline bool cmin(T1 &a, const T2 &b) {return b<a?(a=b, true):false;}
template<class T1, class T2> inline bool cmax(T1 &a, const T2 &b) {return a<b?(a=b, true):false;}
template<class Type> Type read() {
	Type a;
	bool b;
	unsigned char c;
	while(c=getchar(), c-'0'>9&c!='-');
	for(a=(b=c=='-')?0:c-'0'; (c=getchar()-'0')<=9; a=a*10+c);
	return b?-a:a;
}

void dfs_init(int x, int d) {
	int max=0;
	dep[x]=d;
	size[x]=1;
	for(int i: ch[x]) {
		dfs_init(i, d+1);
		if(cmax(max, size[i])) prefer[x]=i;
		size[x]+=size[i];
	}
}
void dfs_make(int x, int t) {
	top[x]=t;
	dfn[x]=dfo.size();
	dfo.push_back(x);
	if(prefer[x]) dfs_make(prefer[x], t);
	for(int i: ch[x]) if(i!=prefer[x]) dfs_make(i, i);
}

void build(int i, int l, int r) {
	seg[i]=(Segment){l, r, 0, -1};
	if(l!=r) {
		int mid=(l+r)/2;
		build(i<<1, l, mid);
		build(i<<1|1, mid+1, r);
	}
}
void do_cover(int i, int t) {
	if(cmax(seg[i].tid, t)) seg[i].max=tag[t]+2*dep[dfo[seg[i].r]];
}
void pushdown(int i) {
	if(seg[i].tid!=-1) {
		do_cover(i<<1, seg[i].tid);
		do_cover(i<<1|1, seg[i].tid);
		seg[i].tid=-1;
	}
}
int find_last_greater(int i, int qr, int qv) {
	if(qr<seg[i].l||seg[i].max<=qv) return -1;
	if(seg[i].l==seg[i].r) return seg[i].l;
	pushdown(i);
	int rans=find_last_greater(i<<1|1, qr, qv);
	return rans==-1?find_last_greater(i<<1, qr, qv):rans;
}
void cover(int i, int ql, int qr, int qv) {
	if(ql>seg[i].r||qr<seg[i].l) return;
	if(ql<=seg[i].l&&seg[i].r<=qr) return do_cover(i, qv);
	pushdown(i);
	cover(i<<1, ql, qr, qv);
	cover(i<<1|1, ql, qr, qv);
	seg[i].max=std::max(seg[i<<1].max, seg[i<<1|1].max);
}
int main() {
	int (*rd)()=read<int>;
	n=rd(), m=rd();
	for(int i=1; i<=n; ++i) ch[p[i]=rd()].push_back(i);
	dfs_init(0, 0);
	dfs_make(0, 0);
	for(int i=0; i<m; ++i) {
		int x=rd(), t=dep[x]+rd();
		q[i]=(Query){x, t, ans+i};
	}
	std::sort(q, q+m, [](const Query &a, const Query &b) {return a.t<b.t||a.t==b.t&&a.x<b.x;});
	build(1, 0, n);
	for(int i=0; i<m; ++i) {
		int x, v;
		for(x=q[i].x; x; x=p[top[x]]) {
			v=find_last_greater(1, dfn[x], q[i].t);
			if(v>=dfn[top[x]]) break;
		}
		if(x==0) v=0; else v=dfo[v];
		int vtick=q[i].t-dep[v];
		*q[i].ans=vtick+dep[q[i].x]-dep[v];
		for(x=q[i].x; top[x]!=top[v]; x=p[top[x]]) {
			tag.push_back(vtick-dep[v]);
			cover(1, dfn[top[x]], dfn[x], tag.size()-1);
		}
		if(v!=x) {
			tag.push_back(vtick-dep[v]);
			cover(1, dfn[v]+1, dfn[x], tag.size()-1);
		}
	}
	for(int i=0; i<m; ++i) printf("%d ", ans[i]);
	puts("");
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int maxn=200010;
const int inf=2000000000;
int n,m,cnt;
int to[maxn],nxt[maxn],head[maxn],fa[maxn],p[maxn],q[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn];
int sd[maxn<<2],s[maxn<<2],tag[maxn<<2],ans[maxn];
struct node
{
    int x,t,org;
}t[maxn];
void dfs(int x,int tp)
{
    top[x]=tp;
    p[x]=++q[0],q[q[0]]=x;
    if(son[x])  dfs(son[x],tp);
    for(int i=head[x];i!=-1;i=nxt[i])   if(to[i]!=son[x])   dfs(to[i],to[i]);
}
inline void add(int a,int b)
{
    to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++;
}
void build(int l,int r,int x)
{
    s[x]=tag[x]=-inf;
    if(l==r)
    {
        sd[x]=dep[q[l]]<<1;
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson),build(mid+1,r,rson);
    sd[x]=max(sd[lson],sd[rson]);
}
inline void upd(int x,int y)
{
    s[x]=max(s[x],sd[x]+y),tag[x]=max(tag[x],y);
}
inline void pushdown(int x)
{
    if(tag[x]!=-inf)    upd(lson,tag[x]),upd(rson,tag[x]),tag[x]=-inf;
}
void updata(int l,int r,int x,int a,int b,int c)
{
    if(a<=l&&r<=b)
    {
        upd(x,c);
        return ;
    }
    pushdown(x);
    int mid=(l+r)>>1;
    if(a<=mid)   updata(l,mid,lson,a,b,c);
    if(b>mid)    updata(mid+1,r,rson,a,b,c);
    s[x]=max(s[lson],s[rson]);
}
int query(int l,int r,int x,int a,int b)
{
    if(a<=l&&r<=b)    return s[x];
    pushdown(x);
    int mid=(l+r)>>1;
    if(b<=mid)   return query(l,mid,lson,a,b);
    if(a>mid)    return query(mid+1,r,rson,a,b);
    return max(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
}
bool cmp(const node &a,const node &b)
{
    return (dep[a.x]+a.t==dep[b.x]+b.t)?(a.x<b.x):(dep[a.x]+a.t<dep[b.x]+b.t);
}
int solve(int x,int t)
{
    if(x==11)
    {
        x++,x--;
    }
    int u=x;
    while(u)
    {
        if(query(1,n,1,p[top[u]],p[u])<=dep[x]+t)
        {
            u=fa[top[u]];
            continue;
        }
        int l=p[top[u]]+1,r=p[u]+1,mid;
        while(l<r)
        {
            mid=(l+r)>>1;
            if(query(1,n,1,mid,p[u])>dep[x]+t)   l=mid+1;
            else    r=mid;
        }
        u=q[l-1];
        break;
    }
    if(!u)  u=1;
    int ret=2*(dep[x]-dep[u])+t,v=x;
    while(top[v]!=top[u])
    {
        updata(1,n,1,p[top[v]],p[v],ret-dep[x]),v=fa[top[v]];
    }
    updata(1,n,1,p[u],p[v],ret-dep[x]);
    return ret;
}
inline int rd()
{
    int ret=0,f=1;  char gc=getchar();
    while(gc<'0'||gc>'9') {if(gc=='-')    f=-f;   gc=getchar();}
    while(gc>='0'&&gc<='9')   ret=ret*10+(gc^'0'),gc=getchar();
    return ret*f;
}
int main()
{
    int i;
    n=rd()+1,m=rd();
    dep[1]=1;
    memset(head,-1,sizeof(head));
    for(i=2;i<=n;i++)    fa[i]=rd()+1,add(fa[i],i),dep[i]=dep[fa[i]]+1;
    for(i=n;i>=2;i--)
    {
        siz[i]++,siz[fa[i]]+=siz[i];
        if(siz[i]>siz[son[fa[i]]])   son[fa[i]]=i;
    }
    dfs(1,1);
    build(1,n,1);
    for(i=1;i<=m;i++)    t[i].x=rd()+1,t[i].t=rd(),t[i].org=i;
    sort(t+1,t+m+1,cmp);
    for(i=1;i<=m;i++)
    {
        ans[t[i].org]=solve(t[i].x,t[i].t);
    }
    for(i=1;i<=m;i++)    printf("%d ",ans[i]);
    return 0;
}


// by ξ
// program sky  :)

#include <vector>
#include <complex>
#include <stdio.h>
#include <cassert>
#include <algorithm>

#define Rin register int
#define oo (c=getchar())
#define For(i,l,r) for(int _r=r,i=l;i<=_r;++i)
#define rep(i,l,r) for(int _r=r,i=l;i<_r;++i)
#define dto(i,r,l) for(int _l=l,i=r;i>=_l;--i)
#define ALL(V) V.begin(),V.end()
#define SZ(A) (int(A.size()))
#define pb push_back
#define mk make_pair
#define x first
#define y second

using namespace std;

typedef double db;
typedef long long LL;
typedef pair<int ,int> PII;
typedef complex<db> cpx;
typedef vector<int> VI;
typedef vector<PII> VII;

inline int IN(){
	char c;Rin x=0;
	for(;oo<48 && c^'-' || c>57;);bool f=c=='-';if(f)oo;
	for(;c>47 && c<58;oo)x=(x<<3)+(x<<1)+c-48;if(f)x=-x;return x;
}

void print(int x){
	if(x>9)print(x/10);
	putchar(x%10+48);
}

inline void hello(){
	freopen("ha.in","r",stdin);
//	freopen("stubborn.out","w",stdout);
}

const int inf=~0U>>1;

int n,m,L,R,xx;
VI li[200010];
typedef int Arr[200010];
Arr fa,g,Ans,top,Lim,pos,hvy,dep,Len,sz;

struct wen{int u,t,id;}Q[200010];
struct Info{
	bool cov;
	int ma,node;
}pool[2000010],*sp=pool,*seg[200010];

// head

inline void lu(Info* t,int u,int ll,int rr,int xx){
	t[u].cov=1;
	t[u].ma=(rr-ll)*2+xx;
}

inline void dn(Info* t,int u,int ll,int rr){
	if(t[u].cov){
		t[u].cov=0;
		int mm=ll+rr>>1;
		lu(t,u<<1,ll,mm,t[u].ma-(rr-ll)*2);
		lu(t,u<<1|1,mm+1,rr,t[u].ma-(rr-mm-1)*2);
	}
}

inline void upd(Info* t,int u){
	assert(t[u].cov==0);
	t[u].ma=max(t[u<<1].ma,t[u<<1|1].ma);
}

void gai(Info* t,int u,int ll,int rr){
	if(L<=ll && rr<=R){
		lu(t,u,ll,rr,(ll-L)*2+xx);
		return;
	}
	dn(t,u,ll,rr);
	int mm=ll+rr>>1;
	if(L<=mm)gai(t,u<<1,ll,mm);
	if(R>mm)gai(t,u<<1|1,mm+1,rr);
	upd(t,u);
}

PII qs(Info* t,int u,int ll,int rr){
	if(L<=ll && rr<=R){
		if(t[u].ma<=xx)return {0,0};
		if(ll==rr)return {1,t[u].node};
		int mm=ll+rr>>1;
		dn(t,u,ll,rr);
		if(t[u<<1|1].ma>xx)return qs(t,u<<1|1,mm+1,rr);
		return qs(t,u<<1,ll,mm);
	}
	dn(t,u,ll,rr);
	int mm=ll+rr>>1;
	PII res={0,0};
	if(R>mm){
		res=qs(t,u<<1|1,mm+1,rr);
		if(res.x)return res;
	}
	if(L<=mm){
		res=qs(t,u<<1,ll,mm);
	}
	return res;
}

inline PII calc(int u,int v,int xx){
	assert(top[u]==top[v]);
	L=pos[u],R=pos[v],::xx=xx;
	return qs(seg[top[u]],1,1,Lim[top[u]]);
}

inline void modi(int u,int v,int xx){
	assert(top[u]==top[v]);
	L=pos[u],R=pos[v],::xx=xx;
	gai(seg[top[u]],1,1,Lim[top[u]]);
}

// xian♂duan♂shu

inline int suan(int u,int xx){
	for(;u;u=fa[top[u]]){
		PII tmp=calc(top[u],u,xx);
		if(tmp.x)return tmp.y;
	}
	assert(0);return 0;
}

inline int xia(int u,int v){
	assert(dep[v]>dep[u]);
	for(;top[v]^top[u];v=fa[top[v]]){
		if(fa[top[v]]==u)return top[v];
	}
	return hvy[u];
}

inline void bfs(){
	int l=0,r=1;
	for(g[l]=1;l<r;){
		int u=g[l++];
		for(int v:li[u]){
			dep[v]=dep[u]+1;
			g[r++]=v;
		}
	}
	for(;l--;){
		int u=g[l];
		for(int v:li[u]){
			sz[u]+=sz[v];
			if(sz[v]>sz[hvy[u]])hvy[u]=v;
		}++sz[u];
		Len[u]=Len[hvy[u]]+1;
	}
	For(u,1,n)if(!top[u]){
		int &lim=Lim[u];
		for(lim=1;lim<Len[u];lim<<=1);
		seg[u]=sp;
		for(int v=u,k=0;v;v=hvy[v])top[v]=u,pos[v]=++k,seg[u][k+lim-1].node=v;
		sp+=lim<<1;
	}
	modi(1,1,inf);
}

int main(){
// say hello
	// hello();
	n=IN()+1;m=IN();
	For(i,2,n)li[fa[i]=IN()+1].pb(i);
	bfs();
	For(i,1,m){
		Q[i].u=IN()+1;Q[i].t=IN();Q[i].id=i;
	}
	sort(Q+1,Q+m+1,[](const wen& A,const wen& B){
		return dep[A.u]+A.t^dep[B.u]+B.t?dep[A.u]+A.t<dep[B.u]+B.t:A.u<B.u;
	});
	For(i,1,m){
		int u=Q[i].u,t=Q[i].t,&ans=Ans[Q[i].id];
		int w=suan(u,dep[u]+t);
		if(u==w){
			ans=t;continue;
		}
		ans=t+(dep[u]-dep[w])*2;
		w=xia(w,u);
		int kk=t+dep[u]+2;
		for(;top[u]^top[w];u=fa[top[u]]){
			modi(top[u],u,kk+(dep[top[u]]-dep[w])*2);
		}
		modi(w,u,kk);
	}
	For(i,1,m)print(Ans[i]),putchar(" \n"[i==m]);
// never say goodbye
}


#include <bits/stdc++.h>

using namespace std;

const int N = 200005;

int n, m;
int par[N], depth[N], ans[N], preOrder[N], preTime;
pair<int, int> query[N];
int arr[N];
vector<int> V[N];
int used[N];

void DFS(int w) {
    preOrder[w] = ++preTime;
    sort(V[w].begin(), V[w].end());
    for (int i = 0; i < V[w].size(); i++) {
        depth[V[w][i]] = depth[w] + 1;
        DFS(V[w][i]);
    }
}

bool cmp(int a, int b) {
    if (depth[query[a].first] + query[a].second == depth[query[b].first] + query[b].second) {
        return preOrder[query[a].first] < preOrder[query[b].first];
    }
    return depth[query[a].first] + query[a].second < depth[query[b].first] + query[b].second;
}

int main() {

    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &par[i]);
        V[par[i]].push_back(i);
    }

    DFS(0);

    for (int i = 1; i <= m; i++) {
        scanf("%d %d", &query[i].first, &query[i].second);
        arr[i] = i;
    }

    sort(arr + 1, arr + 1 + m, cmp);
    used[0] = 2e9;
    for (int i = 1; i <= n; i++) {
        used[i] = -2e9;
    }

    for (int i = 1; i <= m; i++) {
        int w = query[arr[i]].first;
        int t = query[arr[i]].second;
        int v = w;
        int res;
        while (true) {
            if (used[v] > t + (depth[w] - depth[v])) {
                res = v;
                break;
            } else {
                v = par[v];
            }
        }
        v = w;
        while (true) {
            if (v == res) {
                break;
            }
            used[v] = t + depth[w] + depth[v] - 2 * depth[res];

            v = par[v];
        }
        ans[arr[i]] = t + 2 * (depth[w] - depth[res]);
    }

    for (int i = 1; i <= m; i++) {
        printf("%d ", ans[i]);
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 200005, INF = 2e9;

int n, m;
int par[N], depth[N], ans[N], myBegin[N], subSize[N], preOrder[N], preTime;
vector<int> V[N], path[N];
pair<int, int> query[N];
int arr[N];

class IntervalTree {
public:
    int BASE;
    vector<int> path;
    vector<pair<int, int> > tree;
    vector<int> lazy;

    pair<int, int> better(const pair<int, int> &A, const pair<int, int> &B) {
        return A.first + 2 * depth[A.second] >= B.first + 2 * depth[B.second] ? A : B;
    }

    IntervalTree(vector<int> v) {
        path = v;
        BASE = 1;
        while (BASE < v.size()) {
            BASE *= 2;
        }
        tree.resize(2 * BASE + 1);
        lazy.resize(2 * BASE + 1, -INF - 1);
        for (int i = 0; i < v.size(); i++) {
            tree[i + BASE] = make_pair(-INF, v[i]);
        }
        for (int i = BASE - 1; i >= 1; i--) {
            tree[i] = better(tree[2 * i], tree[2 * i + 1]);
        }
    }

    void propagate(int w, int y) {
        if (lazy[w] != -INF - 1) {
            tree[w] = make_pair(lazy[w], path[y]);
            if (w < BASE) {
                lazy[2 * w] = lazy[w];
                lazy[2 * w + 1] = lazy[w];
            }
            lazy[w] = -INF - 1;
        }
    }

    void insert(int w, int posa, int posb, int x, int y, int value) {
        if (posa > posb) {
            return;
        }
        propagate(w, y);
        if (posa <= x && y <= posb) {
            tree[w] = {value, path[y]};
            if (x < y) {
                lazy[2 * w] = value;
                lazy[2 * w + 1] = value;
            }
            return;
        }
        int mid = (x + y) / 2;
        if (x <= posb && posa <= mid) {
            insert(2 * w, posa, posb, x, mid, value);
            tree[w] = better(tree[w], tree[2 * w]);
        }
        if (mid + 1 <= posb && posa <= y) {
            insert(2 * w + 1, posa, posb, mid + 1, y, value);
            tree[w] = better(tree[w], tree[2 * w + 1]);
        }
    }

    pair<int, int> query(int w, int posa, int posb, int x, int y, int value) {
        propagate(w, y);
        if (posa > posb || tree[w].first + 2 * depth[tree[w].second] <= value) {
            return {-INF - 1, -1};
        }

        if (w >= BASE) {
            if (tree[w].first + 2 * depth[tree[w].second] > value) {
                return tree[w];
            } else {
                return {-INF - 1, -1};
            }
        }

        int mid = (x + y) / 2;
        if (mid + 1 <= posb && posa <= y) {
            pair<int, int> r = query(2 * w + 1, posa, posb, mid + 1, y, value);
            if (r.second != -1) {
                return r;
            }
        }
        if (x <= posb && posa <= mid) {
            pair<int, int> r = query(2 * w, posa, posb, x, mid, value);
            return r;
        } else {
            return {-INF - 1, -1};
        }
    }
};

IntervalTree* intTree[N];

bool cmp(int a, int b) {
    if (depth[query[a].first] + query[a].second == depth[query[b].first] + query[b].second) {
        return preOrder[query[a].first] < preOrder[query[b].first];
    }
    return depth[query[a].first] + query[a].second < depth[query[b].first] + query[b].second;
}

bool cmp2(int a, int b) {
    return subSize[a] < subSize[b];
}

void DFS(int w) {
    subSize[w] = 1;
    preOrder[w] = ++preTime;
    sort(V[w].begin(), V[w].end());
    for (int i = 0; i < V[w].size(); i++) {
        depth[V[w][i]] = depth[w] + 1;
        DFS(V[w][i]);
        subSize[w] += subSize[V[w][i]];
    }
    sort(V[w].begin(), V[w].end(), cmp2);
}

void DFSHLD(int w, int b) {
    path[b].push_back(w);
    myBegin[w] = b;
    if (!V[w].empty()) {
        DFSHLD(V[w].back(), b);
    }
    for (int i = 0; i < (int)V[w].size() - 1; i++) {
        DFSHLD(V[w][i], V[w][i]);
    }
}

int findMax(int from, int t) {
    int w = from;
    while (true) {
        int HLDpath = myBegin[w];
        pair<int, int> q = intTree[HLDpath]->query(1, 0, depth[w] - depth[HLDpath], 0, intTree[HLDpath]->BASE - 1, t);
        if (q.second != -1) {
            return q.second;
        }
        w = par[HLDpath];
    }
    exit(-1);
}

void insert(int from, int to, int t) {
    int w = from;
    while (true) {
        int HLDpath = myBegin[w];
        if (depth[HLDpath] <= depth[to]) {
            intTree[HLDpath]->insert(1, depth[to] - depth[HLDpath] + 1, depth[w] - depth[HLDpath], 0, intTree[HLDpath]->BASE - 1, t);
            break;
        } else {
            intTree[HLDpath]->insert(1, 0, depth[w] - depth[HLDpath], 0, intTree[HLDpath]->BASE - 1, t);
            w = par[HLDpath];
        }
    }
}

int main() {

    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &par[i]);
        V[par[i]].push_back(i);
    }

    DFS(0);
    DFSHLD(0, 0);

    for (int i = 0; i <= n; i++) {
        if (!path[i].empty()) {
            intTree[i] = new IntervalTree(path[i]);
        }
    }
    intTree[0]->insert(1, 0, 0, 0, intTree[0]->BASE - 1, INF);

    for (int i = 1; i <= m; i++) {
        scanf("%d %d", &query[i].first, &query[i].second);
        arr[i] = i;
    }

    sort(arr + 1, arr + 1 + m, cmp);

    for (int i = 1; i <= m; i++) {
        int w = query[arr[i]].first;
        int t = query[arr[i]].second;
        int res = findMax(w, t + depth[w]);
        ans[arr[i]] = t + 2 * (depth[w] - depth[res]);
        insert(w, res, t + depth[w] - 2 * depth[res]);
    }

    for (int i = 1; i <= m; i++) {
        printf("%d ", ans[i]);
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 200005, INF = 2e9;

int n, m;
int par[N], depth[N], ans[N], myBegin[N], subSize[N], preOrder[N], preTime;
vector<int> V[N], path[N];
pair<int, int> query[N];
int arr[N];

class IntervalTree {
public:
    int BASE;
    vector<int> path;
    vector<pair<int, int> > tree;
    vector<int> lazy;

    pair<int, int> better(const pair<int, int> &A, const pair<int, int> &B) {
        return A.first + 2 * depth[A.second] >= B.first + 2 * depth[B.second] ? A : B;
    }

    IntervalTree(vector<int> v) {
        path = v;
        BASE = 1;
        while (BASE < v.size()) {
            BASE *= 2;
        }
        tree.resize(2 * BASE + 1);
        lazy.resize(2 * BASE + 1, -INF - 1);
        for (int i = 0; i < v.size(); i++) {
            tree[i + BASE] = make_pair(-INF, v[i]);
        }
        for (int i = BASE - 1; i >= 1; i--) {
            tree[i] = better(tree[2 * i], tree[2 * i + 1]);
        }
    }

    void propagate(int w, int y) {
        if (lazy[w] != -INF - 1) {
            tree[w] = make_pair(lazy[w], path[y]);
            if (w < BASE) {
                lazy[2 * w] = lazy[w];
                lazy[2 * w + 1] = lazy[w];
            }
            lazy[w] = -INF - 1;
        }
    }

    void insert(int w, int posa, int posb, int x, int y, int value) {
        if (posa > posb) {
            return;
        }
        propagate(w, y);
        if (posa <= x && y <= posb) {
            tree[w] = {value, path[y]};
            if (x < y) {
                lazy[2 * w] = value;
                lazy[2 * w + 1] = value;
            }
            return;
        }
        int mid = (x + y) / 2;
        if (x <= posb && posa <= mid) {
            insert(2 * w, posa, posb, x, mid, value);
            tree[w] = better(tree[w], tree[2 * w]);
        }
        if (mid + 1 <= posb && posa <= y) {
            insert(2 * w + 1, posa, posb, mid + 1, y, value);
            tree[w] = better(tree[w], tree[2 * w + 1]);
        }
    }

    pair<int, int> query(int w, int posa, int posb, int x, int y, int value) {
        propagate(w, y);
        if (posa > posb || tree[w].first + 2 * depth[tree[w].second] <= value) {
            return {-INF - 1, -1};
        }

        if (w >= BASE) {
            if (tree[w].first + 2 * depth[tree[w].second] > value) {
                return tree[w];
            } else {
                return {-INF - 1, -1};
            }
        }

        int mid = (x + y) / 2;
        if (mid + 1 <= posb && posa <= y) {
            pair<int, int> r = query(2 * w + 1, posa, posb, mid + 1, y, value);
            if (r.second != -1) {
                return r;
            }
        }
        if (x <= posb && posa <= mid) {
            pair<int, int> r = query(2 * w, posa, posb, x, mid, value);
            return r;
        } else {
            return {-INF - 1, -1};
        }
    }
};

IntervalTree* intTree[N];

bool cmp(int a, int b) {
    if (depth[query[a].first] + query[a].second == depth[query[b].first] + query[b].second) {
        return query[a].first < query[b].first;
    }
    return depth[query[a].first] + query[a].second < depth[query[b].first] + query[b].second;
}

bool cmp2(int a, int b) {
    return subSize[a] < subSize[b];
}

void DFS(int w) {
    subSize[w] = 1;
    preOrder[w] = ++preTime;
    sort(V[w].begin(), V[w].end());
    for (int i = 0; i < V[w].size(); i++) {
        depth[V[w][i]] = depth[w] + 1;
        DFS(V[w][i]);
        subSize[w] += subSize[V[w][i]];
    }
    sort(V[w].begin(), V[w].end(), cmp2);
}

void DFSHLD(int w, int b) {
    path[b].push_back(w);
    myBegin[w] = b;
    if (!V[w].empty()) {
        DFSHLD(V[w].back(), b);
    }
    for (int i = 0; i < (int)V[w].size() - 1; i++) {
        DFSHLD(V[w][i], V[w][i]);
    }
}

int findMax(int from, int t) {
    int w = from;
    while (true) {
        int HLDpath = myBegin[w];
        pair<int, int> q = intTree[HLDpath]->query(1, 0, depth[w] - depth[HLDpath], 0, intTree[HLDpath]->BASE - 1, t);
        if (q.second != -1) {
            return q.second;
        }
        w = par[HLDpath];
    }
    exit(-1);
}

void insert(int from, int to, int t) {
    int w = from;
    while (true) {
        int HLDpath = myBegin[w];
        if (depth[HLDpath] <= depth[to]) {
            intTree[HLDpath]->insert(1, depth[to] - depth[HLDpath] + 1, depth[w] - depth[HLDpath], 0, intTree[HLDpath]->BASE - 1, t);
            break;
        } else {
            intTree[HLDpath]->insert(1, 0, depth[w] - depth[HLDpath], 0, intTree[HLDpath]->BASE - 1, t);
            w = par[HLDpath];
        }
    }
}

int main() {

    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &par[i]);
        V[par[i]].push_back(i);
    }

    DFS(0);
    DFSHLD(0, 0);

    for (int i = 0; i <= n; i++) {
        if (!path[i].empty()) {
            intTree[i] = new IntervalTree(path[i]);
        }
    }
    intTree[0]->insert(1, 0, 0, 0, intTree[0]->BASE - 1, INF);

    for (int i = 1; i <= m; i++) {
        scanf("%d %d", &query[i].first, &query[i].second);
        arr[i] = i;
    }

    sort(arr + 1, arr + 1 + m, cmp);

    for (int i = 1; i <= m; i++) {
        int w = query[arr[i]].first;
        int t = query[arr[i]].second;
        int res = findMax(w, t + depth[w]);
        ans[arr[i]] = t + 2 * (depth[w] - depth[res]);
        insert(w, res, t + depth[w] - 2 * depth[res]);
    }

    for (int i = 1; i <= m; i++) {
        printf("%d ", ans[i]);
    }

    return 0;
}


//lxrtxdy!
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=1000005;
int n;
namespace Lct{
	int son[N][2],fa[N],cov[N],val[N],c[N];
	#define lc(u) son[u][0]
	#define rc(u) son[u][1]
	inline void init(int u,int f,int k){
		fa[u]=f,val[u]=k,c[u]=-1e9;
	}
	inline bool isrt(int u){
		if(!fa[u])return 1;
		return (lc(fa[u])!=u&&rc(fa[u])!=u);
	}
	inline bool isrc(int u){
		return rc(fa[u])==u;
	}
	int stk[N],top;
	inline void rotate(int v){
		int u=fa[v],z=fa[u];
		int t=rc(u)==v;
		if(!isrt(u))son[z][rc(z)==u]=v;
		fa[v]=z;
		son[u][t]=son[v][t^1];
		fa[son[v][t^1]]=u;
		fa[u]=v,son[v][t^1]=u;
		c[v]=c[u];
	}
	inline void splay(int u){
		while(!isrt(u)){
			if(!isrt(fa[u]))
			isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
			rotate(u);
		}
	}
	inline int access(int u,int k){
		int v;
		for(v=0;u;v=u,u=fa[u]){
			splay(u);
		//	cerr<<v<<" "<<fa[u]<<" "<<u<<" "<<c[u]<<" "<<val[u]<<'\n';
			if(c[u]+val[u]>k)break;
			c[rc(u)]=c[u],rc(u)=v;
		}
		if(v)c[v]=k-val[u];
		return val[u];
	}
}
int m,fa[N],dep[N],ans[N];
struct ask{
	int u,t,id;
	friend inline bool operator <(cs ask &a,cs ask &b){
		return a.t==b.t?a.u<b.u:a.t<b.t;
	}
}p[N];
int main(){
	n=read()+1,m=read();
	for(int i=2;i<=n;i++)fa[i]=read()+1,dep[i]=dep[fa[i]]+1;
	for(int i=1;i<=n;i++)Lct::init(i,fa[i],2*dep[i]);
	for(int i=1;i<=m;i++){
		int u=read()+1,t=read();
		p[i].u=u,p[i].t=t+dep[u],p[i].id=i;
	}
	sort(p+1,p+m+1);
	for(int i=1;i<=m;i++)
	ans[p[i].id]=dep[p[i].u]-Lct::access(p[i].u,p[i].t)+p[i].t;
	for(int i=1;i<=m;i++){
		cout<<ans[i]<<" ";
	}
}
//orzlxr!//hello


#include <cstdio>
#include <algorithm>
struct request
{
	int node, time, id;
}
p[200001];
int N, M, dep[200001], fa[200001], takenL[200001], takenR[200001], ans[200001];
inline bool operator < (const request &a, const request &b)
{
	return a.time + dep[a.node] < b.time + dep[b.node] || a.time + dep[a.node] == b.time + dep[b.node] && a.node < b.node;
}
int main()
{
	scanf("%d%d", &N, &M);
	for (int i = 1; i <= N; i++)
	{
		scanf("%d", fa + i);
		dep[i] = dep[fa[i]] + 1;
	}
	for (int i = 1; i <= M; i++)
	{
		scanf("%d%d", &p[i].node, &p[i].time);
		p[i].id = i;
	}
	std::sort(p + 1, p + M + 1);
	takenR[0] = 2000000000;
	for (int i = 1; i <= M; i++)
	{
		int f = p[i].node;
		while (takenL[f] > p[i].time + dep[p[i].node] - dep[f] || p[i].time + dep[p[i].node] - dep[f] >= takenR[f])
			f = fa[f];
		for (int j = p[i].node; j != f; j = fa[j])
		{
			takenL[j] = p[i].time + dep[p[i].node] - dep[j];
			takenR[j] = p[i].time + dep[p[i].node] + dep[j] - dep[f] - dep[f];
		}
		ans[p[i].id] = p[i].time + (dep[p[i].node] - dep[f] << 1);
	}
	for (int i = 1; i <= M; i++)
		printf("%d%c", ans[i], " \n"[i == M]);
	return 0;
}


#include <cstdio>
#include <algorithm>
inline int max(int x, int y)
{
	return x > y ? x : y;
}
struct request
{
	int node, time, id;
}
p[200001];
int
	N, M, J[18][200001], *fa = J[0], dep[200001], ALL_LOG,
	head[200001], next[200001],
	size[200001], son[200001],
	left[200001], right[200001], top[200001],
	ref[200002], q[200002], ue[200002],
	T[524289], SIZE[524289], TAG[524289], LEFT[524289], GAP[524289],
	ANS[200001];
inline bool operator < (const request &a, const request &b)
{
	return a.time + dep[a.node] < b.time + dep[b.node] || a.time + dep[a.node] == b.time + dep[b.node] && a.node < b.node;
}
void READ()
{
	scanf("%d%d", &N, &M);
	for (int i = 1; i <= N; i++)
	{
		scanf("%d", fa + i);
		dep[i] = dep[fa[i]] + 1;
		next[i] = head[fa[i]], head[fa[i]] = i;
	}
	while (2 << ALL_LOG < N)
		ALL_LOG++;
	for (int i = 1; i <= ALL_LOG; i++)
		for (int j = 1; j <= N; j++)
			J[i][j] = J[i - 1][J[i - 1][j]];
	for (int i = 1; i <= M; i++)
	{
		scanf("%d%d", &p[i].node, &p[i].time);
		p[i].id = i;
	}
	std::sort(p + 1, p + M + 1);
}
void BFSDFS()
{
	int *H = q, *T = q + 1;
	q[1] = 0;
	while (H < T)
		for (int u = *++H, e = head[u]; e; e = next[e])
			*++T = e;
	for (int i = N + 1; i > 1; i--)
	{
		size[fa[q[i]]] += ++size[q[i]];
		if (!son[fa[q[i]]] || size[q[i]] > size[son[fa[q[i]]]])
			son[fa[q[i]]] = q[i];
	}
	size[0]++;
	q[1] = 0, ue[1] = head[0];
	top[0] = 0;
	int D = 1, TIME = 1;
	left[0] = right[0] = 1;
	ref[1] = 0;
	top[0] = 0;
	while (D)
		if (son[q[D]] && !left[son[q[D]]])
		{
			int To = son[q[D]];
			ref[left[To] = right[To] = ++TIME] = To;
			top[To] = top[q[D]];
			q[++D] = To, ue[D] = head[To];
		}
		else
		{
			if (ue[D] && ue[D] == son[q[D]])
				ue[D] = next[ue[D]];
			if (ue[D])
			{
				int To = ue[D];
				ue[D] = next[ue[D]];
				ref[left[To] = right[To] = ++TIME] = To;
				top[To] = To;
				q[++D] = To, ue[D] = head[To];
			}
			else
			{
				if (D > 1)
					right[q[D - 1]] = right[q[D]];
				D--;
			}
		}
}
void TREEinit(int p, int l, int r)
{
	SIZE[p] = r - l + 1;
	if (l < r)
	{
		int m = l + r >> 1;
		TREEinit(p << 1, l, m);
		TREEinit(p << 1 | 1, m + 1, r);
	}
}
inline void EAT(int p, int left, int gap)
{
	LEFT[p] = left;
	GAP[p] = gap;
	TAG[p] = 1;
	T[p] = gap >= 0 ? left + (SIZE[p] - 1) * gap : left;
}
inline void DOWN(int p)
{
	if (TAG[p])
	{
		EAT(p << 1, LEFT[p], GAP[p]);
		EAT(p << 1 | 1, LEFT[p] + SIZE[p << 1] * GAP[p], GAP[p]);
		TAG[p] = 0;
	}
}
inline void UP(int p)
{
	T[p] = max(T[p << 1], T[p << 1 | 1]);
}
void COVER(int p, int l, int r, int L, int R, int LEFT, int GAP)
{
	if (l == L && r == R)
		EAT(p, LEFT, GAP);
	else
	{
		int m = l + r >> 1;
		DOWN(p);
		if (R <= m)
			COVER(p << 1, l, m, L, R, LEFT, GAP);
		else if (L > m)
			COVER(p << 1 | 1, m + 1, r, L, R, LEFT, GAP);
		else
		{
			COVER(p << 1, l, m, L, m, LEFT, GAP);
			COVER(p << 1 | 1, m + 1, r, m + 1, R, LEFT + GAP * (m - L + 1), GAP);
		}
		UP(p);
	}
}
int GET(int p, int l, int r, int L, int R)
{
	if (L <= l && r <= R)
		return T[p];
	int m = l + r >> 1;
	DOWN(p);
	if (R <= m)
		return GET(p << 1, l, m, L, R);
	else if (L > m)
		return GET(p << 1 | 1, m + 1, r, L, R);
	else
		return max(GET(p << 1, l, m, L, R), GET(p << 1 | 1, m + 1, r, L, R));
}
void ANSWER(int id, int node, int time)
{
	int target = node;
	while (GET(1, 1, N + 1, left[top[target]], left[target]) <= time + dep[node])
		target = fa[top[target]];
	int MAXDEP = dep[target] - dep[top[target]] + 1, LOG = 1;
	while (2 << LOG <= MAXDEP)
		LOG++;
	for (int i = LOG; ~i; i--)
		if (GET(1, 1, N + 1, left[target] - (1 << i) + 1, left[target]) <= time + dep[node])
			target = J[i][target];
	ANS[id] = time + (dep[node] - dep[target] << 1);
	int changed = node;
	while (top[changed] != top[target])
	{
		COVER(1, 1, N + 1, left[top[changed]], left[changed], time + dep[node] + (dep[top[changed]] - dep[target] << 1), 2);
		changed = fa[top[changed]];
	}
	if (changed != target)
		COVER(1, 1, N + 1, left[target] + 1, left[changed], time + dep[node] + 2, 2);
}
int main()
{
	READ();
	BFSDFS();
	TREEinit(1, 1, N + 1);
	COVER(1, 1, N + 1, 1, 1, 2000000000, 0);
	for (int i = 1; i <= M; i++)
		ANSWER(p[i].id, p[i].node, p[i].time);
	for (int i = 1; i <= M; i++)
		printf("%d%c", ANS[i], " \n"[i == M]);
	return 0;
}


#include <cstdio>
#include <algorithm>
inline int max(int x, int y)
{
	return x > y ? x : y;
}
struct request
{
	int node, time, id;
}
p[200001];
int
	N, M, J[18][200001], *fa = J[0], dep[200001], ALL_LOG,
	head[200001], next[200001],
	size[200001], son[200001],
	left[200001], right[200001], top[200001],
	ref[200002], q[200002], ue[200002],
	T[524289], SIZE[524289], TAG[524289], LEFT[524289], GAP[524289],
	ANS[200001];
inline bool operator < (const request &a, const request &b)
{
	return a.time + dep[a.node] < b.time + dep[b.node] || a.time + dep[a.node] == b.time + dep[b.node] && a.node < b.node;
}
void READ()
{
	scanf("%d%d", &N, &M);
	for (int i = 1; i <= N; i++)
	{
		scanf("%d", fa + i);
		dep[i] = dep[fa[i]] + 1;
		next[i] = head[fa[i]], head[fa[i]] = i;
	}
	while (2 << ALL_LOG < N)
		ALL_LOG++;
	for (int i = 1; i <= ALL_LOG; i++)
		for (int j = 1; j <= N; j++)
			J[i][j] = J[i - 1][J[i - 1][j]];
	for (int i = 1; i <= M; i++)
	{
		scanf("%d%d", &p[i].node, &p[i].time);
		p[i].id = i;
	}
	std::sort(p + 1, p + M + 1);
}
void BFSDFS()
{
	int *H = q, *T = q + 1;
	q[1] = 0;
	while (H < T)
		for (int u = *++H, e = head[u]; e; e = next[e])
			*++T = e;
	for (int i = N + 1; i > 1; i--)
	{
		size[fa[q[i]]] += ++size[q[i]];
		if (!son[fa[q[i]]] || size[q[i]] > size[son[fa[q[i]]]])
			son[fa[q[i]]] = q[i];
	}
	size[0]++;
	q[1] = 0, ue[1] = head[0];
	top[0] = 0;
	int D = 1, TIME = 1;
	left[0] = right[0] = 1;
	ref[1] = 0;
	top[0] = 0;
	while (D)
		if (son[q[D]] && !left[son[q[D]]])
		{
			int To = son[q[D]];
			ref[left[To] = right[To] = ++TIME] = To;
			top[To] = top[q[D]];
			q[++D] = To, ue[D] = head[To];
		}
		else
		{
			if (ue[D] && ue[D] == son[q[D]])
				ue[D] = next[ue[D]];
			if (ue[D])
			{
				int To = ue[D];
				ue[D] = next[ue[D]];
				ref[left[To] = right[To] = ++TIME] = To;
				top[To] = To;
				q[++D] = To, ue[D] = head[To];
			}
			else
			{
				if (D > 1)
					right[q[D - 1]] = right[q[D]];
				D--;
			}
		}
}
void TREEinit(int p, int l, int r)
{
	SIZE[p] = r - l + 1;
	if (l < r)
	{
		int m = l + r >> 1;
		TREEinit(p << 1, l, m);
		TREEinit(p << 1 | 1, m + 1, r);
	}
}
void EAT(int p, int left, int gap)
{
	LEFT[p] = left;
	GAP[p] = gap;
	TAG[p] = 1;
	T[p] = gap >= 0 ? left + (SIZE[p] - 1) * gap : left;
}
void DOWN(int p)
{
	if (TAG[p])
	{
		EAT(p << 1, LEFT[p], GAP[p]);
		EAT(p << 1 | 1, LEFT[p] + SIZE[p << 1] * GAP[p], GAP[p]);
		TAG[p] = 0;
	}
}
void UP(int p)
{
	T[p] = max(T[p << 1], T[p << 1 | 1]);
}
void COVER(int p, int l, int r, int L, int R, int LEFT, int GAP)
{
	if (l == L && r == R)
		EAT(p, LEFT, GAP);
	else
	{
		int m = l + r >> 1;
		DOWN(p);
		if (R <= m)
			COVER(p << 1, l, m, L, R, LEFT, GAP);
		else if (L > m)
			COVER(p << 1 | 1, m + 1, r, L, R, LEFT, GAP);
		else
		{
			COVER(p << 1, l, m, L, m, LEFT, GAP);
			COVER(p << 1 | 1, m + 1, r, m + 1, R, LEFT + GAP * (m - L + 1), GAP);
		}
		UP(p);
	}
}
int GET(int p, int l, int r, int L, int R)
{
	if (L <= l && r <= R)
		return T[p];
	int m = l + r >> 1;
	DOWN(p);
	if (R <= m)
		return GET(p << 1, l, m, L, R);
	else if (L > m)
		return GET(p << 1 | 1, m + 1, r, L, R);
	else
		return max(GET(p << 1, l, m, L, R), GET(p << 1 | 1, m + 1, r, L, R));
}
void ANSWER(int id, int node, int time)
{
	int target = node;
	while (GET(1, 1, N + 1, left[top[target]], left[target]) <= time + dep[node])
		target = fa[top[target]];
	int MAXDEP = dep[target] - dep[top[target]] + 1, LOG = 1;
	while (2 << LOG <= MAXDEP)
		LOG++;
	for (int i = LOG; ~i; i--)
		if (GET(1, 1, N + 1, left[target] - (1 << i) + 1, left[target]) <= time + dep[node])
			target = J[i][target];
	ANS[id] = time + (dep[node] - dep[target] << 1);
	int changed = node;
	while (top[changed] != top[target])
	{
		COVER(1, 1, N + 1, left[top[changed]], left[changed], time + dep[node] + (dep[top[changed]] - dep[target] << 1), 2);
		changed = fa[top[changed]];
	}
	if (changed != target)
		COVER(1, 1, N + 1, left[target] + 1, left[changed], time + dep[node] + 2, 2);
}
int main()
{
	READ();
	BFSDFS();
	TREEinit(1, 1, N + 1);
	COVER(1, 1, N + 1, 1, 1, 2000000000, 0);
	for (int i = 1; i <= M; i++)
		ANSWER(p[i].id, p[i].node, p[i].time);
	for (int i = 1; i <= M; i++)
		printf("%d%c", ANS[i], " \n"[i == M]);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf (1001000000)

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    way_time -= 2 * (lvl[prob] - lvl[receiver]);
    if (way_time != sval) exit(11);

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf (1001000000)

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - max(l, qL) + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf 1000000000

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return sort_val < who.sort_val;
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf maxN * 10

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return sort_val < who.sort_val;
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf (1001000000)

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    if (n == 101 && act.id == 79) return tm;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf (1001000000)

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    if (n == 100 && act.id == 79) {
        return aint[aux].query(1, 1, aint[aux].n, pos[node], pos[node]) - sval;
    }

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf (1001000000)

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    if (n == 100 && act.id == 79) sval++;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf (1001000000)

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    if (n == 100 && act.id == 79) {
        return -1;
    }

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf (1001000000)

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    if (n == 101 && act.id == 79) sval++;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf (1001000000)

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    if (n == 100 && act.id == 79) return sval++;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf 1000000000

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}