#include<bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;

const int N = 2e5 + 5;
const long long INF = 2e9;

int n, m, dp[N], d[N], og[N], son[N], pr[N], top[N], num[N], sz, p[N], ans[N], a[N], b[N];
int t[5 * N], ob[5 * N];
vector < int > g[N];

void build(int v, int l, int r){
    ob[v] = -1;
    if(l == r){
        if(l == 1){
            t[v] = INF;
        }
        return;
    }
    int mid = (r + l) >> 1;
    build(v + v, l, mid);
    build(v + v + 1, mid + 1, r);
    t[v] = max(t[v + v], t[v + v + 1]);
}

inline void push(int v, int l, int r){
    if(ob[v] != -1){
        ob[v + v + 1] = t[v + v + 1] = ob[v];
        int mid = (r + l) >> 1;
        ob[v + v] = t[v + v] = ob[v] - 2 * (r - mid);
        ob[v] = -1;
    }
}

int mx(int v, int l, int r, int tl, int tr){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return -INF;
    }
    if(tl <= l && r <= tr){
        return t[v];
    }
    int mid = (r + l) >> 1;
    return max(mx(v + v, l, mid, tl, tr), mx(v + v + 1, mid + 1, r, tl, tr));
}

int get(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(t[v] <= val || l > r || l > tr || tl > r){
        return -1;
    }
    if(l == r){
        return og[l];
    }
    int mid = (r + l) >> 1;
    int y = get(v + v + 1, mid + 1, r, tl, tr, val);
    return y == -1 ? get(v + v, l, mid, tl, tr, val) : y;
}

void update(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return;
    }
    if(tl <= l && r <= tr){
        t[v] = ob[v] = val - 2 * (tr - r);
        return;
    }
    int mid = (r + l) >> 1;
    update(v + v, l, mid, tl, tr, val);
    update(v + v + 1, mid + 1, r, tl, tr, val);
    t[v] = max(t[v + v], t[v + v + 1]);
}

void dfs(int v, int depth = 0){
    dp[v] = 1;
    d[v] = depth;
    for(int to : g[v]){
        dfs(to, depth + 1);
        pr[to] = v;
        dp[v] += dp[to];
        if(!son[v] || (dp[to] > dp[son[v]])){
            son[v] = to;
        }
    }
}

void hld(int v){
    sz++;
    og[sz] = v;
    num[v] = sz;
    if(son[v]){
        top[son[v]] = top[v];
        hld(son[v]);
    }
    for(int to : g[v]){
        if(to != son[v]){
            top[to] = to;
            hld(to);
        }
    }
}

inline bool cmp(int x, int y){
    return d[a[x]] + b[x] < d[a[y]] + b[y] || (d[a[x]] + b[x] == d[a[y]] + b[y] && a[x] < a[y]);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++){
        int x;
        scanf("%d", &x);
        g[x].push_back(i);
    }
    dfs(0);
    hld(0);
    n++;
    build(1, 1, n);
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &a[i], &b[i]);
        p[i] = i;
    }
    sort(p + 1, p + m + 1, cmp);
    for(int i = 1; i <= m; i++){
        //cout << p[i] << "\n";
        int x = a[p[i]], t = b[p[i]], v;
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                break;
            }
            x = pr[top[x]];
        }
        ans[p[i]] = t + 2 * (d[a[p[i]]] - d[v]);
        x = a[p[i]];
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                if(v != x){
                    update(1, 1, n, num[v] + 1, num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
                }
                break;
            }
            else{
                update(1, 1, n, num[top[x]], num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
            }
            x = pr[top[x]];
        }
    }
    for(int i = 1; i <= m; i++){
        printf("%d ", ans[i]);
    }
}


#include<bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5;
const long long INF = 2e9;

int n, m, dp[N], d[N], og[N], son[N], pr[N], top[N], num[N], sz, p[N], ans[N], a[N], b[N];
int t[5 * N], ob[5 * N];
vector < int > g[N];

void build(int v, int l, int r){
    ob[v] = -1;
    if(l == r){
        if(l == 1){
            t[v] = INF;
        }
        return;
    }
    int mid = (r + l) >> 1;
    build(v + v, l, mid);
    build(v + v + 1, mid + 1, r);
    t[v] = max(t[v + v], t[v + v + 1]);
}

inline void push(int v, int l, int r){
    if(ob[v] != -1){
        ob[v + v + 1] = t[v + v + 1] = ob[v];
        int mid = (r + l) >> 1;
        ob[v + v] = t[v + v] = ob[v] - 2 * (r - mid);
        ob[v] = -1;
    }
}

int mx(int v, int l, int r, int tl, int tr){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return -INF;
    }
    if(tl <= l && r <= tr){
        return t[v];
    }
    int mid = (r + l) >> 1;
    return max(mx(v + v, l, mid, tl, tr), mx(v + v + 1, mid + 1, r, tl, tr));
}

int get(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(t[v] <= val || l > r || l > tr || tl > r){
        return -1;
    }
    if(l == r){
        return og[l];
    }
    int mid = (r + l) >> 1;
    int y = get(v + v + 1, mid + 1, r, tl, tr, val);
    return y == -1 ? get(v + v, l, mid, tl, tr, val) : y;
}

void update(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return;
    }
    if(tl <= l && r <= tr){
        t[v] = ob[v] = val - 2 * (tr - r);
        return;
    }
    int mid = (r + l) >> 1;
    update(v + v, l, mid, tl, tr, val);
    update(v + v + 1, mid + 1, r, tl, tr, val);
    t[v] = max(t[v + v], t[v + v + 1]);
}

void dfs(int v, int depth = 0){
    dp[v] = 1;
    d[v] = depth;
    for(int to : g[v]){
        dfs(to, depth + 1);
        pr[to] = v;
        dp[v] += dp[to];
        if(!son[v] || (dp[to] > dp[son[v]])){
            son[v] = to;
        }
    }
}

void hld(int v){
    sz++;
    og[sz] = v;
    num[v] = sz;
    if(son[v]){
        top[son[v]] = top[v];
        hld(son[v]);
    }
    for(int to : g[v]){
        if(to != son[v]){
            top[to] = to;
            hld(to);
        }
    }
}

inline bool cmp(int x, int y){
    return d[a[x]] + b[x] < d[a[y]] + b[y] || (d[a[x]] + b[x] == d[a[y]] + b[y] && a[x] < a[y]);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++){
        int x;
        scanf("%d", &x);
        g[x].push_back(i);
    }
    dfs(0);
    hld(0);
    n++;
    build(1, 1, n);
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &a[i], &b[i]);
        p[i] = i;
    }
    sort(p + 1, p + m + 1, cmp);
    for(int i = 1; i <= m; i++){
        //cout << p[i] << "\n";
        int x = a[p[i]], t = b[p[i]], v;
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                break;
            }
            x = pr[top[x]];
        }
        ans[p[i]] = t + 2 * (d[a[p[i]]] - d[v]);
        x = a[p[i]];
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                if(v != x){
                    update(1, 1, n, num[v] + 1, num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
                }
                break;
            }
            else{
                update(1, 1, n, num[top[x]], num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
            }
            x = pr[top[x]];
        }
    }
    for(int i = 1; i <= m; i++){
        printf("%d ", ans[i]);
    }
}


#include<bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
using namespace std;

const int N = 2e5 + 5;
const long long INF = 2e9;

int n, m, dp[N], d[N], og[N], son[N], pr[N], top[N], num[N], sz, p[N], ans[N], a[N], b[N];
int t[5 * N], ob[5 * N];
vector < int > g[N];

void build(int v, int l, int r){
    ob[v] = -1;
    if(l == r){
        if(l == 1){
            t[v] = INF;
        }
        return;
    }
    int mid = (r + l) >> 1;
    build(v + v, l, mid);
    build(v + v + 1, mid + 1, r);
    t[v] = max(t[v + v], t[v + v + 1]);
}

inline void push(int v, int l, int r){
    if(ob[v] != -1){
        ob[v + v + 1] = t[v + v + 1] = ob[v];
        int mid = (r + l) >> 1;
        ob[v + v] = t[v + v] = ob[v] - 2 * (r - mid);
        ob[v] = -1;
    }
}

int mx(int v, int l, int r, int tl, int tr){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return -INF;
    }
    if(tl <= l && r <= tr){
        return t[v];
    }
    int mid = (r + l) >> 1;
    return max(mx(v + v, l, mid, tl, tr), mx(v + v + 1, mid + 1, r, tl, tr));
}

int get(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(t[v] <= val || l > r || l > tr || tl > r){
        return -1;
    }
    if(l == r){
        return og[l];
    }
    int mid = (r + l) >> 1;
    int y = get(v + v + 1, mid + 1, r, tl, tr, val);
    return y == -1 ? get(v + v, l, mid, tl, tr, val) : y;
}

void update(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return;
    }
    if(tl <= l && r <= tr){
        t[v] = ob[v] = val - 2 * (tr - r);
        return;
    }
    int mid = (r + l) >> 1;
    update(v + v, l, mid, tl, tr, val);
    update(v + v + 1, mid + 1, r, tl, tr, val);
    t[v] = max(t[v + v], t[v + v + 1]);
}

void dfs(int v, int depth = 0){
    dp[v] = 1;
    d[v] = depth;
    for(int to : g[v]){
        dfs(to, depth + 1);
        pr[to] = v;
        dp[v] += dp[to];
        if(!son[v] || (dp[to] > dp[son[v]])){
            son[v] = to;
        }
    }
}

void hld(int v){
    sz++;
    og[sz] = v;
    num[v] = sz;
    if(son[v]){
        top[son[v]] = top[v];
        hld(son[v]);
    }
    for(int to : g[v]){
        if(to != son[v]){
            top[to] = to;
            hld(to);
        }
    }
}

inline bool cmp(int x, int y){
    return d[a[x]] + b[x] < d[a[y]] + b[y] || (d[a[x]] + b[x] == d[a[y]] + b[y] && a[x] < a[y]);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++){
        int x;
        scanf("%d", &x);
        g[x].push_back(i);
    }
    dfs(0);
    hld(0);
    n++;
    build(1, 1, n);
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &a[i], &b[i]);
        p[i] = i;
    }
    sort(p + 1, p + m + 1, cmp);
    for(int i = 1; i <= m; i++){
        //cout << p[i] << "\n";
        int x = a[p[i]], t = b[p[i]], v;
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                break;
            }
            x = pr[top[x]];
        }
        ans[p[i]] = t + 2 * (d[a[p[i]]] - d[v]);
        x = a[p[i]];
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                if(v != x){
                    update(1, 1, n, num[v] + 1, num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
                }
                break;
            }
            else{
                update(1, 1, n, num[top[x]], num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
            }
            x = pr[top[x]];
        }
    }
    for(int i = 1; i <= m; i++){
        printf("%d ", ans[i]);
    }
}


#include<cstdio>
#include<vector>
#include<algorithm>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
using namespace std;

const int N = 3e5 + 5;
const long long INF = 2e9;

int n, m, dp[N], d[N], og[N], son[N], pr[N], top[N], num[N], sz, p[N], ans[N], a[N], b[N];
int t[5 * N], ob[5 * N];
vector < int > g[N];

void build(int v, int l, int r){
    ob[v] = -1;
    if(l == r){
        if(l == 1){
            t[v] = INF;
        }
        return;
    }
    int mid = (r + l) >> 1;
    build(v + v, l, mid);
    build(v + v + 1, mid + 1, r);
    t[v] = max(t[v + v], t[v + v + 1]);
}

inline void push(int v, int l, int r){
    if(ob[v] != -1){
        ob[v + v + 1] = t[v + v + 1] = ob[v];
        int mid = (r + l) >> 1;
        ob[v + v] = t[v + v] = ob[v] - 2 * (r - mid);
        ob[v] = -1;
    }
}

int mx(int v, int l, int r, int tl, int tr){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return -INF;
    }
    if(tl <= l && r <= tr){
        return t[v];
    }
    int mid = (r + l) >> 1;
    return max(mx(v + v, l, mid, tl, tr), mx(v + v + 1, mid + 1, r, tl, tr));
}

int get(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(t[v] <= val || l > r || l > tr || tl > r){
        return -1;
    }
    if(l == r){
        return og[l];
    }
    int mid = (r + l) >> 1;
    int y = get(v + v + 1, mid + 1, r, tl, tr, val);
    return y == -1 ? get(v + v, l, mid, tl, tr, val) : y;
}

void update(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return;
    }
    if(tl <= l && r <= tr){
        t[v] = ob[v] = val - 2 * (tr - r);
        return;
    }
    int mid = (r + l) >> 1;
    update(v + v, l, mid, tl, tr, val);
    update(v + v + 1, mid + 1, r, tl, tr, val);
    t[v] = max(t[v + v], t[v + v + 1]);
}

void dfs(int v, int depth = 0){
    dp[v] = 1;
    d[v] = depth;
    for(int to : g[v]){
        dfs(to, depth + 1);
        pr[to] = v;
        dp[v] += dp[to];
        if(!son[v] || (dp[to] > dp[son[v]])){
            son[v] = to;
        }
    }
}

void hld(int v){
    sz++;
    og[sz] = v;
    num[v] = sz;
    if(son[v]){
        top[son[v]] = top[v];
        hld(son[v]);
    }
    for(int to : g[v]){
        if(to != son[v]){
            top[to] = to;
            hld(to);
        }
    }
}

inline bool cmp(int x, int y){
    return d[a[x]] + b[x] < d[a[y]] + b[y] || (d[a[x]] + b[x] == d[a[y]] + b[y] && a[x] < a[y]);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++){
        int x;
        scanf("%d", &x);
        g[x].push_back(i);
    }
    dfs(0);
    hld(0);
    n++;
    build(1, 1, n);
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &a[i], &b[i]);
        p[i] = i;
    }
    sort(p + 1, p + m + 1, cmp);
    for(int i = 1; i <= m; i++){
        //cout << p[i] << "\n";
        int x = a[p[i]], t = b[p[i]], v;
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                break;
            }
            x = pr[top[x]];
        }
        ans[p[i]] = t + 2 * (d[a[p[i]]] - d[v]);
        x = a[p[i]];
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                if(v != x){
                    update(1, 1, n, num[v] + 1, num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
                }
                break;
            }
            else{
                update(1, 1, n, num[top[x]], num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
            }
            x = pr[top[x]];
        }
    }
    for(int i = 1; i <= m; i++){
        printf("%d ", ans[i]);
    }
}


#include<bits/stdc++.h>
using namespace std;

const int N = 3e5 + 5;
const long long INF = 2e9;

int n, m, dp[N], d[N], og[N], son[N], pr[N], top[N], num[N], sz, p[N], ans[N], a[N], b[N];
int t[5 * N], ob[5 * N];
vector < int > g[N];

void build(int v, int l, int r){
    ob[v] = -1;
    if(l == r){
        if(l == 1){
            t[v] = INF;
        }
        return;
    }
    int mid = (r + l) >> 1;
    build(v + v, l, mid);
    build(v + v + 1, mid + 1, r);
    t[v] = max(t[v + v], t[v + v + 1]);
}

inline void push(int v, int l, int r){
    if(ob[v] != -1){
        ob[v + v + 1] = t[v + v + 1] = ob[v];
        int mid = (r + l) >> 1;
        ob[v + v] = t[v + v] = ob[v] - 2 * (r - mid);
        ob[v] = -1;
    }
}

int mx(int v, int l, int r, int tl, int tr){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return -INF;
    }
    if(tl <= l && r <= tr){
        return t[v];
    }
    int mid = (r + l) >> 1;
    return max(mx(v + v, l, mid, tl, tr), mx(v + v + 1, mid + 1, r, tl, tr));
}

int get(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(t[v] <= val || l > r || l > tr || tl > r){
        return -1;
    }
    if(l == r){
        return og[l];
    }
    int mid = (r + l) >> 1;
    int y = get(v + v + 1, mid + 1, r, tl, tr, val);
    return y == -1 ? get(v + v, l, mid, tl, tr, val) : y;
}

void update(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return;
    }
    if(tl <= l && r <= tr){
        t[v] = ob[v] = val - 2 * (tr - r);
        return;
    }
    int mid = (r + l) >> 1;
    update(v + v, l, mid, tl, tr, val);
    update(v + v + 1, mid + 1, r, tl, tr, val);
    t[v] = max(t[v + v], t[v + v + 1]);
}

void dfs(int v, int depth = 0){
    dp[v] = 1;
    d[v] = depth;
    for(int to : g[v]){
        dfs(to, depth + 1);
        pr[to] = v;
        dp[v] += dp[to];
        if(!son[v] || (dp[to] > dp[son[v]])){
            son[v] = to;
        }
    }
}

void hld(int v){
    sz++;
    og[sz] = v;
    num[v] = sz;
    if(son[v]){
        top[son[v]] = top[v];
        hld(son[v]);
    }
    for(int to : g[v]){
        if(to != son[v]){
            top[to] = to;
            hld(to);
        }
    }
}

inline bool cmp(int x, int y){
    return d[a[x]] + b[x] < d[a[y]] + b[y] || (d[a[x]] + b[x] == d[a[y]] + b[y] && a[x] < a[y]);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++){
        int x;
        scanf("%d", &x);
        g[x].push_back(i);
    }
    dfs(0);
    hld(0);
    n++;
    build(1, 1, n);
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &a[i], &b[i]);
        p[i] = i;
    }
    sort(p + 1, p + m + 1, cmp);
    for(int i = 1; i <= m; i++){
        //cout << p[i] << "\n";
        int x = a[p[i]], t = b[p[i]], v;
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                break;
            }
            x = pr[top[x]];
        }
        ans[p[i]] = t + 2 * (d[a[p[i]]] - d[v]);
        x = a[p[i]];
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                if(v != x){
                    update(1, 1, n, num[v] + 1, num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
                }
                break;
            }
            else{
                update(1, 1, n, num[top[x]], num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
            }
            x = pr[top[x]];
        }
    }
    for(int i = 1; i <= m; i++){
        printf("%d ", ans[i]);
    }
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
using namespace std;

const int N = 2e5 + 5;
const long long INF = 2e9;

int n, m, dp[N], d[N], og[N], son[N], pr[N], top[N], num[N], sz, p[N], ans[N], a[N], b[N];
int t[5 * N], ob[5 * N];
vector < int > g[N];

void build(int v, int l, int r){
    ob[v] = -1;
    if(l == r){
        if(l == 1){
            t[v] = INF;
        }
        return;
    }
    int mid = (r + l) >> 1;
    build(v + v, l, mid);
    build(v + v + 1, mid + 1, r);
    t[v] = max(t[v + v], t[v + v + 1]);
}

inline void push(int v, int l, int r){
    if(ob[v] != -1){
        ob[v + v + 1] = t[v + v + 1] = ob[v];
        int mid = (r + l) >> 1;
        ob[v + v] = t[v + v] = ob[v] - 2 * (r - mid);
        ob[v] = -1;
    }
}

int mx(int v, int l, int r, int tl, int tr){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return -INF;
    }
    if(tl <= l && r <= tr){
        return t[v];
    }
    int mid = (r + l) >> 1;
    return max(mx(v + v, l, mid, tl, tr), mx(v + v + 1, mid + 1, r, tl, tr));
}

int get(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(t[v] <= val || l > r || l > tr || tl > r){
        return -1;
    }
    if(l == r){
        return og[l];
    }
    int mid = (r + l) >> 1;
    int y = get(v + v + 1, mid + 1, r, tl, tr, val);
    return y == -1 ? get(v + v, l, mid, tl, tr, val) : y;
}

void update(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return;
    }
    if(tl <= l && r <= tr){
        t[v] = ob[v] = val - 2 * (tr - r);
        return;
    }
    int mid = (r + l) >> 1;
    update(v + v, l, mid, tl, tr, val);
    update(v + v + 1, mid + 1, r, tl, tr, val);
    t[v] = max(t[v + v], t[v + v + 1]);
}

void dfs(int v, int depth = 0){
    dp[v] = 1;
    d[v] = depth;
    for(int to : g[v]){
        dfs(to, depth + 1);
        pr[to] = v;
        dp[v] += dp[to];
        if(!son[v] || (dp[to] > dp[son[v]])){
            son[v] = to;
        }
    }
}

void hld(int v){
    sz++;
    og[sz] = v;
    num[v] = sz;
    if(son[v]){
        top[son[v]] = top[v];
        hld(son[v]);
    }
    for(int to : g[v]){
        if(to != son[v]){
            top[to] = to;
            hld(to);
        }
    }
}

inline bool cmp(int x, int y){
    return d[a[x]] + b[x] < d[a[y]] + b[y] || (d[a[x]] + b[x] == d[a[y]] + b[y] && a[x] < a[y]);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++){
        int x;
        scanf("%d", &x);
        g[x].push_back(i);
    }
    dfs(0);
    hld(0);
    n++;
    build(1, 1, n);
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &a[i], &b[i]);
        p[i] = i;
    }
    sort(p + 1, p + m + 1, cmp);
    for(int i = 1; i <= m; i++){
        //cout << p[i] << "\n";
        int x = a[p[i]], t = b[p[i]], v;
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                break;
            }
            x = pr[top[x]];
        }
        ans[p[i]] = t + 2 * (d[a[p[i]]] - d[v]);
        x = a[p[i]];
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                if(v != x){
                    update(1, 1, n, num[v] + 1, num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
                }
                break;
            }
            else{
                update(1, 1, n, num[top[x]], num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
            }
            x = pr[top[x]];
        }
    }
    for(int i = 1; i <= m; i++){
        printf("%d ", ans[i]);
    }
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;

const int N = 2e5 + 5;
const long long INF = 2e9;

int n, m, dp[N], d[N], og[N], son[N], pr[N], top[N], num[N], sz, p[N], ans[N], a[N], b[N];
int t[5 * N], ob[5 * N];
vector < int > g[N];

void build(int v, int l, int r){
    ob[v] = -1;
    if(l == r){
        if(l == 1){
            t[v] = INF;
        }
        return;
    }
    int mid = (r + l) >> 1;
    build(v + v, l, mid);
    build(v + v + 1, mid + 1, r);
    t[v] = max(t[v + v], t[v + v + 1]);
}

inline void push(int v, int l, int r){
    if(ob[v] != -1){
        ob[v + v + 1] = t[v + v + 1] = ob[v];
        int mid = (r + l) >> 1;
        ob[v + v] = t[v + v] = ob[v] - 2 * (r - mid);
        ob[v] = -1;
    }
}

int mx(int v, int l, int r, int tl, int tr){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return -INF;
    }
    if(tl <= l && r <= tr){
        return t[v];
    }
    int mid = (r + l) >> 1;
    return max(mx(v + v, l, mid, tl, tr), mx(v + v + 1, mid + 1, r, tl, tr));
}

int get(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(t[v] <= val || l > r || l > tr || tl > r){
        return -1;
    }
    if(l == r){
        return og[l];
    }
    int mid = (r + l) >> 1;
    int y = get(v + v + 1, mid + 1, r, tl, tr, val);
    return y == -1 ? get(v + v, l, mid, tl, tr, val) : y;
}

void update(int v, int l, int r, int tl, int tr, int val){
    push(v, l, r);
    if(l > r || l > tr || tl > r){
        return;
    }
    if(tl <= l && r <= tr){
        t[v] = ob[v] = val - 2 * (tr - r);
        return;
    }
    int mid = (r + l) >> 1;
    update(v + v, l, mid, tl, tr, val);
    update(v + v + 1, mid + 1, r, tl, tr, val);
    t[v] = max(t[v + v], t[v + v + 1]);
}

void dfs(int v, int depth = 0){
    dp[v] = 1;
    d[v] = depth;
    for(int to : g[v]){
        dfs(to, depth + 1);
        pr[to] = v;
        dp[v] += dp[to];
        if(!son[v] || (dp[to] > dp[son[v]])){
            son[v] = to;
        }
    }
}

void hld(int v){
    sz++;
    og[sz] = v;
    num[v] = sz;
    if(son[v]){
        top[son[v]] = top[v];
        hld(son[v]);
    }
    for(int to : g[v]){
        if(to != son[v]){
            top[to] = to;
            hld(to);
        }
    }
}

inline bool cmp(int x, int y){
    return d[a[x]] + b[x] < d[a[y]] + b[y] || (d[a[x]] + b[x] == d[a[y]] + b[y] && a[x] < a[y]);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++){
        int x;
        scanf("%d", &x);
        g[x].push_back(i);
    }
    dfs(0);
    hld(0);
    n++;
    build(1, 1, n);
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &a[i], &b[i]);
        p[i] = i;
    }
    sort(p + 1, p + m + 1, cmp);
    for(int i = 1; i <= m; i++){
        //cout << p[i] << "\n";
        int x = a[p[i]], t = b[p[i]], v;
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                break;
            }
            x = pr[top[x]];
        }
        ans[p[i]] = t + 2 * (d[a[p[i]]] - d[v]);
        x = a[p[i]];
        while(true){
            if(mx(1, 1, n, num[top[x]], num[x]) > t + d[a[p[i]]]){
                v = get(1, 1, n, num[top[x]], num[x], t + d[a[p[i]]]);
                if(v != x){
                    update(1, 1, n, num[v] + 1, num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
                }
                break;
            }
            else{
                update(1, 1, n, num[top[x]], num[x], ans[p[i]] - (d[a[p[i]]] - d[x]) + d[x]);
            }
            x = pr[top[x]];
        }
    }
    for(int i = 1; i <= m; i++){
        printf("%d ", ans[i]);
    }
}


#include <cstdio>
#include <algorithm>
#include <utility>
static const int INF = 0x7fffffff;
static const int MAXN = 200006;
static const int MAXM = 200004;
template <typename T> inline bool upd_max(T &var, const T val) {
    if (var < val) { var = val; return true; } else return false;
}

int n, m, p[MAXN];
int x[MAXM], t[MAXM], qid[MAXM], qans[MAXM];

int head[MAXN], dest[MAXN], next[MAXN];
inline void add_edge(int u, int v) {
    static int w = 0;
    dest[w] = v; next[w] = head[u]; head[u] = w++;
}

// Heavy-light decomposition
int dep[MAXN], sts[MAXN], pfc[MAXN], dfn[MAXN], hct[MAXN], seq[MAXN];
void dfs_first(int u, int d = 0)
{
    dep[u] = d; sts[u] = 1; pfc[u] = -1;
    int max_sts = -1;
    for (int w = head[u]; w != -1; w = next[w]) {
        dfs_first(dest[w], d + 1);
        sts[u] += sts[dest[w]];
        if (upd_max(max_sts, sts[dest[w]])) pfc[u] = dest[w];
    }
}
void dfs_second(int u, int top = 0)
{
    static int epoch = -1;
    seq[dfn[u] = ++epoch] = u; hct[u] = top;
    if (pfc[u] != -1) dfs_second(pfc[u], top);
    for (int w = head[u]; w != -1; w = next[w])
        if (dest[w] != pfc[u]) dfs_second(dest[w], dest[w]);
}

// Segment tree
namespace sgt {

static const int MAXN = ::MAXN * 2;
int sz = 0;
int l[MAXN], r[MAXN], lch[MAXN], rch[MAXN], val[MAXN], tag[MAXN];

inline void push(int idx) {
    if (lch[idx] == -1 || tag[idx] <= -INF) return;
    tag[lch[idx]] = tag[rch[idx]] = tag[idx];
    val[lch[idx]] = r[lch[idx]] * 2 + tag[idx];
    val[rch[idx]] = r[rch[idx]] * 2 + tag[idx];
    tag[idx] = -INF;
}
inline void update(int idx) {
    val[idx] = std::max(val[lch[idx]], val[rch[idx]]);
}

int build(int L, int R) {
    int idx = sz++;
    l[idx] = L, r[idx] = R; val[idx] = tag[idx] = -INF;
    if (L == R) lch[idx] = rch[idx] = -1;
    else {
        int M = (L + R) >> 1;
        lch[idx] = build(L, M);
        rch[idx] = build(M + 1, R);
    }
    return idx;
}

int QL, QR, QV;
void modify(int idx) {
    push(idx);
    if (l[idx] >= QL && r[idx] <= QR) {
        tag[idx] = QV; val[idx] = r[idx] * 2 + QV; return;
    }
    if (r[lch[idx]] >= QL) modify(lch[idx]);
    if (l[rch[idx]] <= QR) modify(rch[idx]);
    update(idx);
}
inline void modify(int L, int R, int V) {
    QL = L, QR = R, QV = V; modify(0);
}

int query(int idx) {
    if (val[idx] <= QV) return -1;
    if (lch[idx] == -1) return l[idx];
    push(idx);
    int ans = -1;
    if (l[rch[idx]] <= QR && (ans = query(rch[idx])) != -1) return ans;
    if (r[lch[idx]] >= QL && (ans = query(lch[idx])) != -1) return ans;
    update(idx);
    return -1;
}
inline int query(int L, int R, int V) {
    QL = L, QR = R, QV = V; return query(0);
}

}

inline bool qid_cmp(const int lhs, const int rhs) {
    return
        std::make_pair(t[lhs] + dep[x[lhs]], x[lhs]) <
        std::make_pair(t[rhs] + dep[x[rhs]], x[rhs]);
}

inline int process_query(int u, int time)
{
    int v = u;
    // Find out where the answer will come from (w=v)
    //printf("Process_Query %d %d\n", u, time);
    while (true) {
        int w = sgt::query(dfn[hct[v]], dfn[v], time + dfn[v]);
        if (w != -1) {
            time += (dep[v] - dep[seq[w]]); v = seq[w]; break;
        }
        if (v == 0) break;
        time += (dep[v] - dep[p[hct[v]]]);
        v = p[hct[v]];
    }
    int ret = time + dep[u] - dep[v];
    // Modify the (u → w=v) path
    while (true) {
        if (hct[u] == hct[v]) {
            if (u != v) sgt::modify(dfn[v] + 1, dfn[u], time - dfn[v]);
            break;
        }
        sgt::modify(dfn[hct[u]], dfn[u], time + dep[u] - dep[v] - dfn[u]);
        u = p[hct[u]];
    }
    //printf("Process_Query %d %d\t* Finish (%d)\n", u, time, ret);
    return ret;
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i <= n; ++i) head[i] = -1;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &p[i]); add_edge(p[i], i);
    }
    dfs_first(0);
    dfs_second(0);
    sgt::build(0, n);
    //for (int i = 0; i <= n; ++i) printf("%d\tDFN=%d PFC=%d HCT=%d\n", i, dfn[i], pfc[i], hct[i]);

    for (int i = 0; i < m; ++i) { scanf("%d%d", &x[i], &t[i]); qid[i] = i; }
    std::sort(qid, qid + m, qid_cmp);
    for (int i = 0; i < m; ++i) qans[qid[i]] = process_query(x[qid[i]], t[qid[i]]);

    for (int i = 0; i < m; ++i) printf("%d%c", qans[i], i == m - 1 ? '\n' : ' ');
    return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<ctime>
using namespace std;
typedef long long ll;
#define sqr(x) ((x)*(x))
#define mp make_pair
#define PI pair<int,int>
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x = 0; char ch = gc(); bool positive = 1;
    for (; !isdigit(ch); ch = gc())	if (ch == '-')	positive = 0;
    for (; isdigit(ch); ch = gc())	x = x * 10 + ch - '0';
    return positive ? x : -x;
}
inline void write(int a){
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(int a){
    if(a<0){
    	a=-a; putchar('-');
    }
    write(a); puts("");
}
const int N=200005,oo=1e9;
int ans[N],fa[N];
pair<PI,int> a[N];
int nedge,wson[N],ed[N],nextt[N],son[N],tree[N<<2],lazy[N<<2],peo[N],deep[N],ti,n,m,pos[N],father[N],in[N],top[N];
inline void aedge(int a,int b){
	nextt[++nedge]=son[a]; son[a]=nedge; ed[nedge]=b;
}
inline void cao(int nod,int r,int x){
	tree[nod]=x+deep[pos[r]]*2; lazy[nod]=x;
	//if(x==11)cout<<pos[r]<<" "<<tree[nod]<<" "<<nod<<endl;
}
inline void pushdown(int nod,int l,int r){
	if(lazy[nod]==-oo)return; int mid=(l+r)>>1; cao(nod<<1,mid,lazy[nod]); cao(nod<<1|1,r,lazy[nod]); lazy[nod]=-oo;
}
inline int ask(int l,int r,int i,int j,int s,int nod){
	//if(s==11)cout<<l<<" "<<r<<" "<<i<<" "<<j<<" "<<tree[nod]<<" "<<lazy[nod]<<" "<<nod<<endl;
	if(l>1&&tree[nod]<=s)return 0;
	if (l==r) return pos[l];
	pushdown(nod,l,r);
	int mid=(l+r)>>1;
	if (j<=mid) return ask(l,mid,i,j,s,nod<<1);
	else if(i>mid) return ask(mid+1,r,i,j,s,nod<<1|1);
	int t=ask(mid+1,r,mid+1,j,s,nod<<1|1); if(t)return t;
	return ask(l,mid,i,mid,s,nod<<1);
}
inline void insert(int l,int r,int i,int j,int s,int nod){
	//if(nod==1)cout<<l<<" "<<r<<" "<<i<<" "<<j<<endl;
	if(l==i&&r==j){
		lazy[nod]=s; cao(nod,r,s); return;
	}
	pushdown(nod,l,r);
	int mid=(l+r)>>1;
    if(j<=mid)insert(l,mid,i,j,s,nod<<1); else
    if(i>mid)insert(mid+1,r,i,j,s,nod<<1|1); else{
    	insert(l,mid,i,mid,s,nod<<1); insert(mid+1,r,mid+1,j,s,nod<<1|1);
	}
	tree[nod]=max(tree[nod<<1],tree[nod<<1|1]);
}
void dfs1(int p){
	peo[p]=1; wson[p]=-1;
	for(int i=son[p];i;i=nextt[i]){
		deep[ed[i]]=deep[p]+1;
		dfs1(ed[i]); peo[p]+=peo[ed[i]];
		if(wson[p]==-1||peo[ed[i]]>peo[wson[p]])wson[p]=ed[i];
	}
}
void dfs2(int p){
	pos[in[p]=++ti]=p;
	if(p==wson[father[p]])top[p]=top[father[p]]; else top[p]=p;
	if(wson[p]!=-1)dfs2(wson[p]);
	for(int i=son[p];i;i=nextt[i])if(ed[i]!=wson[p])dfs2(ed[i]);
}
inline bool cmp(pair<PI,int> a,pair<PI,int> b){
	return a.first.second+deep[a.first.first]==b.first.second+deep[b.first.first]?a.first.first<b.first.first:a.first.second+deep[a.first.first]<b.first.second+deep[b.first.first];
}
void update(int u,int v,int x){
    while(top[u]!=top[v]){
        insert(1,n,in[top[u]],in[u],x,1);
        u=father[top[u]];
    }
    if(u!=v)insert(1,n,in[v]+1,in[u],x,1);
}
int query(int u,int t){
    int ans=deep[u]+t;
    while(1){
        int t=ask(1,n,in[top[u]],in[u],ans,1);if(t)return t;
        u=father[top[u]];
    }
}
int main(){
//	freopen("tree.in","r",stdin); freopen("tree.out","w",stdout);
	n=read()+1; m=read();
	for(int i=1;i<(N<<2);i++)lazy[i]=-oo;
	for(int i=2;i<=n;i++){
		deep[i]=deep[father[i]=read()+1]+1; aedge(father[i],i);
	}
	dfs1(1); dfs2(1);
	for(int i=1;i<=m;i++){
		a[i].first.first=read()+1; a[i].first.second=read(); a[i].second=i;
	}
	//for(int i=1;i<=m;i++)cout<<deep[a[i].first.first]+a[i].first
	sort(&a[1],&a[m+1],cmp);
	for(int i=1;i<=m;i++){
		//writeln(a[i].first.first);
		//cout<<a[i].first.first<<" "<<" "<<ans[a[i].second]<<" "<<deep[a[i].first.first]<<" "<<a[i].first.second<<endl;
		int t=query(a[i].first.first,a[i].first.second);
		ans[a[i].second]=a[i].first.second+(deep[a[i].first.first]-deep[t])*2;
		//cout<<ans[a[i].second]-deep[a[i].first.first]<<" "<<a[i].first.second+deep[a[i].first.first]<<" "<<deep[a[i].first.first]<<endl;
		//writeln(ans[a[i].second]-deep[a[i].first.first]);
		update(a[i].first.first,t,ans[a[i].second]-deep[a[i].first.first]);
	}
	for(int i=1;i<=m;i++)write(ans[i]),putchar(' ');
}


#include<stdio.h>
#include<cstring>
#include<algorithm>
#define ll long long
#define md ((l+r)>>1)
using namespace std;
#include<iostream>
const int N=200100,oo=2e9;
inline int read(){
	int x=0,c=getchar(),f=0;
	for(;c>'9'||c<'0';f=c=='-',c=getchar());
	for(;c>='0'&&c<='9';c=getchar())
	x=(x<<1)+(x<<3)+c-'0';return f?-x:x;
}
inline void write(ll x){
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
int n,m,fa[N],L,h[N],ne[N],to[N];
void addl(int x,int y){
	ne[++L]=h[x];h[x]=L;to[L]=y;
}
int lv[N],sz[N],son[N],top[N],len[N],ti,dfn[N],id[N];
void dfs(int x){
	lv[x]=lv[fa[x]]+1;sz[x]=1;
	for(int y,k=h[x];k;k=ne[k]){
		dfs(y=to[k]);sz[x]+=sz[y];
		if(sz[y]>sz[son[x]])son[x]=y;
	}
}
void dfs(int x,int tp){
	dfn[x]=++ti;id[ti]=x;
	top[x]=tp;len[tp]++;
	if(son[x]<=n)dfs(son[x],tp);
	for(int k=h[x];k;k=ne[k])
	if(to[k]!=son[x])dfs(to[k],to[k]);
}
struct cqz{int x,t,i;}q[N];
inline bool operator<(cqz i,cqz j){
	if(i.t+lv[i.x]==j.t+lv[j.x])return i.x<j.x;
	else return i.t+lv[i.x]<j.t+lv[j.x];
}
struct seg{
	int tu,ps;
}tr[N*4];
int ls[N*4],rs[N*4],cv[N*4],sm,rt[N],ans[N];
void build(int&i,int l,int r){
	i=++sm;tr[i].ps=r;tr[i].tu=-1;cv[i]=-oo;
	if(l==r)return;build(ls[i],l,md);build(rs[i],md+1,r);
}
void down(int i,int l,int r);
seg max(seg x,seg y){
	if(x.tu-(y.ps-x.ps)>y.tu)return x;
	else return y;
}
void cov(int i,int l,int r,int x,int y,int k){
	if(l>=x&&r<=y){
		cv[i]=k;
		tr[i].ps=r;
		tr[i].tu=k+r;
		return;
	}down(i,l,r);
	if(x<=md)cov(ls[i],l,md,x,y,k);
	if(y>md)cov(rs[i],md+1,r,x,y,k);
	tr[i]=max(tr[ls[i]],tr[rs[i]]);
}
void down(int i,int l,int r){
	if(cv[i]==-oo)return;
	cov(ls[i],l,md,l,md,cv[i]);
	cov(rs[i],md+1,r,md+1,r,cv[i]);
	cv[i]=-oo;
}
bool can(seg&w,int x,int t){
	t+=x-w.ps;
	return w.tu>t;
}
int get(int i,int l,int r,int x,int t){
	if(l>x)return 0;
	if(!can(tr[i],x,t))return 0;
	if(l==r)return l;
	down(i,l,r);
	int re=get(rs[i],md+1,r,x,t);
	if(re)return re;
	return get(ls[i],l,md,x,t);
}
void solve(int X,int T,int I){
	int x,y,t,p,r;
	for(x=X,t=T;x>=0;x=fa[y]){
		y=top[x];
		p=lv[x]-lv[y]+1;
		r=get(rt[y],1,len[y],p,t);
		if(r){r=id[dfn[y]+r-1];break;}
		t+=p;
	}
	t=T+lv[X]+lv[X]-lv[r]-lv[r];
	ans[I]=t;
	for(x=X;top[x]!=top[r];x=fa[y]){
		y=top[x];
		p=lv[x]-lv[y]+1;
		t-=p;
		cov(rt[y],1,len[y],1,p,t);
	}
	y=top[x];
	r=lv[r]-lv[y]+1;
	p=lv[x]-lv[y]+1;
	t-=p;
	if(r<p)cov(rt[y],1,len[y],r+1,p,t);
}
int main(){
	//freopen("tree.in","r",stdin);freopen("std.out","w",stdout);
	register int i;
	n=read();m=read();
	fa[0]=-1;
	for(i=1;i<=n;i++)fa[i]=read(),addl(fa[i],i);
	for(i=0;i<=n;i++)son[i]=n+1;
	dfs(0);dfs(0,0);
	for(i=0;i<=n;i++)if(top[i]==i)build(rt[i],1,len[i]);
	cov(rt[0],1,len[0],1,1,oo);
	for(i=1;i<=m;i++)q[i].x=read(),q[i].t=read(),q[i].i=i;
	sort(q+1,q+m+1);
	for(i=1;i<=m;i++)cout<<q[i].i<<endl;
	for(i=1;i<=m;i++)solve(q[i].x,q[i].t,q[i].i);
	for(i=1;i<m;i++)printf("%d ",ans[i]);printf("%d ",ans[m]);
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<ctime>
using namespace std;
typedef long long ll;
#define sqr(x) ((x)*(x))
#define mp make_pair
#define PI pair<int,int>
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x = 0; char ch = gc(); bool positive = 1;
    for (; !isdigit(ch); ch = gc())	if (ch == '-')	positive = 0;
    for (; isdigit(ch); ch = gc())	x = x * 10 + ch - '0';
    return positive ? x : -x;
}
inline void write(int a){
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(int a){
    if(a<0){
    	a=-a; putchar('-');
    }
    write(a); puts("");
}
const int N=200005,oo=1e9;
int ans[N],fa[N];
pair<PI,int> a[N];
int nedge,wson[N],ed[N],nextt[N],son[N],tree[N<<2],lazy[N<<2],peo[N],deep[N],ti,n,m,pos[N],father[N],in[N],top[N];
inline void aedge(int a,int b){
	nextt[++nedge]=son[a]; son[a]=nedge; ed[nedge]=b;
}
inline void cao(int nod,int r,int x){
	tree[nod]=x+deep[pos[r]]*2; lazy[nod]=x;
	//if(x==11)cout<<pos[r]<<" "<<tree[nod]<<" "<<nod<<endl;
}
inline void pushdown(int nod,int l,int r){
	if(lazy[nod]==-oo)return; int mid=(l+r)>>1; cao(nod<<1,mid,lazy[nod]); cao(nod<<1|1,r,lazy[nod]); lazy[nod]=-oo;
}
inline int ask(int l,int r,int i,int j,int s,int nod){
	//if(s==11)cout<<l<<" "<<r<<" "<<i<<" "<<j<<" "<<tree[nod]<<" "<<lazy[nod]<<" "<<nod<<endl;
	if(l>1&&tree[nod]<=s)return 0;
	if (l==r) return pos[l];
	pushdown(nod,l,r);
	int mid=(l+r)>>1;
	if (j<=mid) return ask(l,mid,i,j,s,nod<<1);
	else if(i>mid) return ask(mid+1,r,i,j,s,nod<<1|1);
	int t=ask(mid+1,r,mid+1,j,s,nod<<1|1); if(t)return t;
	return ask(l,mid,i,mid,s,nod<<1);
}
inline void insert(int l,int r,int i,int j,int s,int nod){
	//if(nod==1)cout<<l<<" "<<r<<" "<<i<<" "<<j<<endl;
	if(l==i&&r==j){
		lazy[nod]=s; cao(nod,r,s); return;
	}
	pushdown(nod,l,r);
	int mid=(l+r)>>1;
    if(j<=mid)insert(l,mid,i,j,s,nod<<1); else
    if(i>mid)insert(mid+1,r,i,j,s,nod<<1|1); else{
    	insert(l,mid,i,mid,s,nod<<1); insert(mid+1,r,mid+1,j,s,nod<<1|1);
	}
	tree[nod]=max(tree[nod<<1],tree[nod<<1|1]);
}
void dfs1(int p){
	peo[p]=1; wson[p]=-1;
	for(int i=son[p];i;i=nextt[i]){
		deep[ed[i]]=deep[p]+1;
		dfs1(ed[i]); peo[p]+=peo[ed[i]];
		if(wson[p]==-1||peo[ed[i]]>peo[wson[p]])wson[p]=ed[i];
	}
}
void dfs2(int p){
	pos[in[p]=++ti]=p;
	if(p==wson[father[p]])top[p]=top[father[p]]; else top[p]=p;
	if(wson[p]!=-1)dfs2(wson[p]);
	for(int i=son[p];i;i=nextt[i])if(ed[i]!=wson[p])dfs2(ed[i]);
}
inline bool cmp(pair<PI,int> a,pair<PI,int> b){
	return a.first.second+deep[a.first.first]==b.first.second+deep[b.first.first]?a.second<b.second:a.first.second+deep[a.first.first]<b.first.second+deep[b.first.first];
}
void update(int u,int v,int x){
    while(top[u]!=top[v]){
        insert(1,n,in[top[u]],in[u],x,1);
        u=father[top[u]];
    }
    if(u!=v)insert(1,n,in[v]+1,in[u],x,1);
}
int query(int u,int t){
    int ans=deep[u]+t;
    while(1){
        int t=ask(1,n,in[top[u]],in[u],ans,1);if(t)return t;
        u=father[top[u]];
    }
}
int main(){
//	freopen("tree.in","r",stdin); freopen("tree.out","w",stdout);
	n=read()+1; m=read();
	for(int i=1;i<(N<<2);i++)lazy[i]=-oo;
	for(int i=2;i<=n;i++){
		deep[i]=deep[father[i]=read()+1]+1; aedge(father[i],i);
	}
	dfs1(1); dfs2(1);
	for(int i=1;i<=m;i++){
		a[i].first.first=read()+1; a[i].first.second=read(); a[i].second=i;
	}
	//for(int i=1;i<=m;i++)cout<<deep[a[i].first.first]+a[i].first
	sort(&a[1],&a[m+1],cmp);
	for(int i=1;i<=m;i++){
		//cout<<deep[a[i].first.first]+a[i].first.second<<endl;
		//cout<<a[i].first.first<<" "<<" "<<ans[a[i].second]<<" "<<deep[a[i].first.first]<<" "<<a[i].first.second<<endl;
		int t=query(a[i].first.first,a[i].first.second);
		ans[a[i].second]=a[i].first.second+(deep[a[i].first.first]-deep[t])*2;
		//writeln(a[i].second);
		//cout<<ans[a[i].second]-deep[a[i].first.first]<<" "<<a[i].first.second+deep[a[i].first.first]<<" "<<deep[a[i].first.first]<<endl;
		//writeln(ans[a[i].second]-deep[a[i].first.first]);
		update(a[i].first.first,t,ans[a[i].second]-deep[a[i].first.first]);
	}
	for(int i=1;i<=m;i++)write(ans[i]),putchar(' ');
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<ctime>
using namespace std;
typedef long long ll;
#define sqr(x) ((x)*(x))
#define mp make_pair
#define PI pair<int,int>
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x = 0; char ch = gc(); bool positive = 1;
    for (; !isdigit(ch); ch = gc())	if (ch == '-')	positive = 0;
    for (; isdigit(ch); ch = gc())	x = x * 10 + ch - '0';
    return positive ? x : -x;
}
inline void write(int a){
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(int a){
    if(a<0){
    	a=-a; putchar('-');
    }
    write(a); puts("");
}
const int N=200005;
int ans[N],fa[N];
pair<PI,int> a[N];
int nedge,wson[N],ed[N],nextt[N],son[N],tree[N<<2],lazy[N<<2],peo[N],deep[N],ti,n,m,pos[N],father[N],in[N],top[N];
inline void aedge(int a,int b){
	nextt[++nedge]=son[a]; son[a]=nedge; ed[nedge]=b;
}
inline void cao(int nod,int r,int x){
	tree[nod]=x+deep[pos[r]]*2; lazy[nod]=x;
}
inline void pushdown(int nod,int l,int r){
	if(!lazy[nod])return; int mid=(l+r)>>1; cao(nod<<1,mid,lazy[nod]); cao(nod<<1|1,r,lazy[nod]); lazy[nod]=0;
}
inline int ask(int l,int r,int i,int j,int s,int nod){
	if(l>1&&tree[nod]<=s)return 0;
	if (l==r) return pos[l];
	pushdown(nod,l,r);
	int mid=(l+r)>>1;
	if (j<=mid) return ask(l,mid,i,j,s,nod<<1);
	else if(i>mid) return ask(mid+1,r,i,j,s,nod<<1|1);
	int t=ask(mid+1,r,mid+1,j,s,nod<<1|1); if(t)return t;
	return ask(l,mid,i,mid,s,nod<<1);
}
inline void insert(int l,int r,int i,int j,int s,int nod){
	if(l==i&&r==j){
		lazy[nod]=s; cao(nod,r,s); return;
	}
	int mid=(l+r)>>1;
    if(j<=mid)insert(l,mid,i,j,s,nod<<1); else
    if(i>mid)insert(mid+1,r,i,j,s,nod<<1|1); else{
    	insert(l,mid,i,mid,s,nod<<1); insert(mid+1,r,mid+1,j,s,nod<<1|1);
	}
	tree[nod]=max(tree[nod<<1],tree[nod<<1|1]);
}
void dfs1(int p){
	peo[p]=1; wson[p]=-1;
	for(int i=son[p];i;i=nextt[i]){
		deep[ed[i]]=deep[p]+1;
		dfs1(ed[i]); peo[p]+=peo[ed[i]];
		if(wson[p]==-1||peo[ed[i]]>peo[wson[p]])wson[p]=ed[i];
	}
}
void dfs2(int p){
	pos[in[p]=++ti]=p;
	if(p==wson[father[p]])top[p]=top[father[p]]; else top[p]=p;
	if(wson[p]!=-1)dfs2(wson[p]);
	for(int i=son[p];i;i=nextt[i])if(ed[i]!=wson[p])dfs2(ed[i]);
}
inline bool cmp(pair<PI,int> a,pair<PI,int> b){
	return a.first.second+deep[a.first.first]==b.first.second+deep[b.first.first]?a.first.first<b.first.first:a.first.second+deep[a.first.first]<b.first.second+deep[b.first.first];
}
void update(int u,int v,int x){
	if(x==0)while(1);
    while(top[u]!=top[v]){
        insert(1,n,in[top[u]],in[u],x,1);
        u=father[top[u]];
    }
    if(u!=v)insert(1,n,in[v]+1,in[u],x,1);
}
int query(int u,int t){
    int ans=deep[u]+t;
    while(1){
        int t=ask(1,n,in[top[u]],in[u],ans,1);  if(t)return t;
        u=father[top[u]];
    }
}
int main(){
//freopen("tree.in","r",stdin); freopen("tree.out","w",stdout);
	n=read()+1; m=read();
	for(int i=2;i<=n;i++){
		deep[i]=deep[father[i]=read()+1]+1; aedge(father[i],i);
	}
	dfs1(1); dfs2(1);
	for(int i=1;i<=m;i++){
		a[i].first.first=read()+1; a[i].first.second=read(); a[i].second=i;
	}
	//for(int i=1;i<=m;i++)cout<<deep[a[i].first.first]+a[i].first
	sort(&a[1],&a[m+1],cmp);
	for(int i=1;i<=m;i++){
		int t=query(a[i].first.first,a[i].first.second);
		ans[a[i].second]=a[i].first.second+(deep[a[i].first.first]-deep[t])*2;
		//cout<<ans[a[i].second]-deep[a[i].first.first]<<" "<<a[i].first.second+deep[a[i].first.first]<<" "<<deep[a[i].first.first]<<endl;
		update(a[i].first.first,t,ans[a[i].second]-deep[a[i].first.first]);
	}
	for(int i=1;i<=m;i++)write(ans[i]),putchar(' ');
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<ctime>
using namespace std;
typedef long long ll;
#define sqr(x) ((x)*(x))
#define mp make_pair
#define PI pair<int,int>
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x = 0; char ch = gc(); bool positive = 1;
    for (; !isdigit(ch); ch = gc())	if (ch == '-')	positive = 0;
    for (; isdigit(ch); ch = gc())	x = x * 10 + ch - '0';
    return positive ? x : -x;
}
inline void write(int a){
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(int a){
    if(a<0){
    	a=-a; putchar('-');
    }
    write(a); puts("");
}
const int N=200005,oo=1e9;
int ans[N],fa[N];
pair<PI,int> a[N];
int nedge,wson[N],ed[N],nextt[N],son[N],tree[N<<2],lazy[N<<2],peo[N],deep[N],ti,n,m,pos[N],father[N],in[N],top[N];
inline void aedge(int a,int b){
	nextt[++nedge]=son[a]; son[a]=nedge; ed[nedge]=b;
}
inline void cao(int nod,int r,int x){
	tree[nod]=x+deep[pos[r]]*2; lazy[nod]=x;
}
inline void pushdown(int nod,int l,int r){
	if(lazy[nod]==-oo)return; int mid=(l+r)>>1; cao(nod<<1,mid,lazy[nod]); cao(nod<<1|1,r,lazy[nod]); lazy[nod]=-oo;
}
inline int ask(int l,int r,int i,int j,int s,int nod){
	if(l>1&&tree[nod]<=s)return 0;
	if (l==r) return pos[l];
	pushdown(nod,l,r);
	int mid=(l+r)>>1;
	if (j<=mid) return ask(l,mid,i,j,s,nod<<1);
	else if(i>mid) return ask(mid+1,r,i,j,s,nod<<1|1);
	int t=ask(mid+1,r,mid+1,j,s,nod<<1|1); if(t)return t;
	return ask(l,mid,i,mid,s,nod<<1);
}
inline void insert(int l,int r,int i,int j,int s,int nod){
	//if(nod==1)cout<<l<<" "<<r<<" "<<i<<" "<<j<<endl;
	if(l==i&&r==j){
		lazy[nod]=s; cao(nod,r,s); return;
	}
	int mid=(l+r)>>1;
    if(j<=mid)insert(l,mid,i,j,s,nod<<1); else
    if(i>mid)insert(mid+1,r,i,j,s,nod<<1|1); else{
    	insert(l,mid,i,mid,s,nod<<1); insert(mid+1,r,mid+1,j,s,nod<<1|1);
	}
	tree[nod]=max(tree[nod<<1],tree[nod<<1|1]);
}
void dfs1(int p){
	peo[p]=1; wson[p]=-1;
	for(int i=son[p];i;i=nextt[i]){
		deep[ed[i]]=deep[p]+1;
		dfs1(ed[i]); peo[p]+=peo[ed[i]];
		if(wson[p]==-1||peo[ed[i]]>peo[wson[p]])wson[p]=ed[i];
	}
}
void dfs2(int p){
	pos[in[p]=++ti]=p;
	if(p==wson[father[p]])top[p]=top[father[p]]; else top[p]=p;
	if(wson[p]!=-1)dfs2(wson[p]);
	for(int i=son[p];i;i=nextt[i])if(ed[i]!=wson[p])dfs2(ed[i]);
}
inline bool cmp(pair<PI,int> a,pair<PI,int> b){
	return a.first.second+deep[a.first.first]==b.first.second+deep[b.first.first]?a.first.first<b.first.first:a.first.second+deep[a.first.first]<b.first.second+deep[b.first.first];
}
void update(int u,int v,int x){
    while(top[u]!=top[v]){
        insert(1,n,in[top[u]],in[u],x,1);
        u=father[top[u]];
    }
    if(u!=v)insert(1,n,in[v]+1,in[u],x,1);
}
int query(int u,int t){
    int ans=deep[u]+t;
    while(1){
        int t=ask(1,n,in[top[u]],in[u],ans,1);if(t)return t;
        u=father[top[u]];
    }
}
int main(){
//	freopen("tree.in","r",stdin); freopen("tree.out","w",stdout);
	n=read()+1; m=read();
	for(int i=1;i<(N<<2);i++)lazy[i]=-oo;
	for(int i=2;i<=n;i++){
		deep[i]=deep[father[i]=read()+1]+1; aedge(father[i],i);
	}
	dfs1(1); dfs2(1);
	for(int i=1;i<=m;i++){
		a[i].first.first=read()+1; a[i].first.second=read(); a[i].second=i;
	}
	//for(int i=1;i<=m;i++)cout<<deep[a[i].first.first]+a[i].first
	sort(&a[1],&a[m+1],cmp);
	for(int i=1;i<=m;i++){
		int t=query(a[i].first.first,a[i].first.second);
		ans[a[i].second]=a[i].first.second+(deep[a[i].first.first]-deep[t])*2;
		//cout<<ans[a[i].second]-deep[a[i].first.first]<<" "<<a[i].first.second+deep[a[i].first.first]<<" "<<deep[a[i].first.first]<<endl;
		//writeln(a[i].first.first);
		update(a[i].first.first,t,ans[a[i].second]-deep[a[i].first.first]);
	}
	for(int i=1;i<=m;i++)write(ans[i]),putchar(' ');
}


#include<stdio.h>
#include<cstring>
#include<algorithm>
#define ll long long
#define md ((l+r)>>1)
using namespace std;
#include<iostream>
const int N=200100,oo=2e9;
inline int read(){
	int x=0,c=getchar(),f=0;
	for(;c>'9'||c<'0';f=c=='-',c=getchar());
	for(;c>='0'&&c<='9';c=getchar())
	x=(x<<1)+(x<<3)+c-'0';return f?-x:x;
}
inline void write(ll x){
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
int n,m,fa[N],L,h[N],ne[N],to[N];
void addl(int x,int y){
	ne[++L]=h[x];h[x]=L;to[L]=y;
}
int lv[N],sz[N],son[N],top[N],len[N],ti,dfn[N],id[N];
void dfs(int x){
	lv[x]=lv[fa[x]]+1;sz[x]=1;
	for(int y,k=h[x];k;k=ne[k]){
		dfs(y=to[k]);sz[x]+=sz[y];
		if(sz[y]>sz[son[x]])son[x]=y;
	}
}
void dfs(int x,int tp){
	dfn[x]=++ti;id[ti]=x;
	top[x]=tp;len[tp]++;
	if(son[x]<=n)dfs(son[x],tp);
	for(int k=h[x];k;k=ne[k])
	if(to[k]!=son[x])dfs(to[k],to[k]);
}
struct cqz{int x,t,i;}q[N];
inline bool operator<(cqz i,cqz j){
	if(i.t+lv[i.x]==j.t+lv[j.x])return i.x<j.x;
	else return i.t+lv[i.x]<j.t+lv[j.x];
}
struct seg{
	int tu,ps;
}tr[N*4];
int ls[N*4],rs[N*4],cv[N*4],sm,rt[N],ans[N];
void build(int&i,int l,int r){
	i=++sm;tr[i].ps=r;tr[i].tu=-1;cv[i]=-oo;
	if(l==r)return;build(ls[i],l,md);build(rs[i],md+1,r);
}
void down(int i,int l,int r);
seg max(seg x,seg y){
	if(x.tu-(y.ps-x.ps)>y.tu)return x;
	else return y;
}
void cov(int i,int l,int r,int x,int y,int k){
	if(l>=x&&r<=y){
		cv[i]=k;
		tr[i].ps=r;
		tr[i].tu=k+r;
		return;
	}down(i,l,r);
	if(x<=md)cov(ls[i],l,md,x,y,k);
	if(y>md)cov(rs[i],md+1,r,x,y,k);
	tr[i]=max(tr[ls[i]],tr[rs[i]]);
}
void down(int i,int l,int r){
	if(cv[i]==-oo)return;
	cov(ls[i],l,md,l,md,cv[i]);
	cov(rs[i],md+1,r,md+1,r,cv[i]);
	cv[i]=-oo;
}
bool can(seg&w,int x,int t){
	t+=x-w.ps;
	return w.tu>t;
}
int get(int i,int l,int r,int x,int t){
	if(l>x)return 0;
	if(!can(tr[i],x,t))return 0;
	if(l==r)return l;
	down(i,l,r);
	int re=get(rs[i],md+1,r,x,t);
	if(re)return re;
	return get(ls[i],l,md,x,t);
}
void solve(int X,int T,int I){
	int x,y,t,p,r;
	for(x=X,t=T;x>=0;x=fa[y]){
		y=top[x];
		p=lv[x]-lv[y]+1;
		r=get(rt[y],1,len[y],p,t);
		if(r){r=id[dfn[y]+r-1];break;}
		t+=p;
	}
	t=T+lv[X]+lv[X]-lv[r]-lv[r];
	ans[I]=t;
	for(x=X;top[x]!=top[r];x=fa[y]){
		y=top[x];
		p=lv[x]-lv[y]+1;
		t-=p;
		cov(rt[y],1,len[y],1,p,t);
	}
	y=top[x];
	r=lv[r]-lv[y]+1;
	p=lv[x]-lv[y]+1;
	t-=p;
	if(r<p)cov(rt[y],1,len[y],r+1,p,t);
}
int main(){
	//freopen("tree.in","r",stdin);freopen("std.out","w",stdout);
	register int i;
	n=read();m=read();
	fa[0]=-1;
	for(i=1;i<=n;i++)fa[i]=read(),addl(fa[i],i);
	for(i=0;i<=n;i++)son[i]=n+1;
	dfs(0);dfs(0,0);
	for(i=0;i<=n;i++)if(top[i]==i)build(rt[i],1,len[i]);
	cov(rt[0],1,len[0],1,1,oo);
	for(i=1;i<=m;i++)q[i].x=read(),q[i].t=read(),q[i].i=i;
	sort(q+1,q+m+1);
	//for(i=1;i<=m;i++)cout<<q[i].i<<endl;
	for(i=1;i<=m;i++)solve(q[i].x,q[i].t,q[i].i);
	for(i=1;i<m;i++)printf("%d ",ans[i]);printf("%d ",ans[m]);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define re register
struct nd
{
	int v;
	nd*ch[2],*fa;
	bool rt(){return (!fa)||(fa->ch[0]!=this&&fa->ch[1]!=this);}
	bool tp(){return fa->ch[1]==this;}
	void rotate()
	{
		re bool k=tp();re nd*x=fa;v=x->v;
		fa=x->fa;if(!x->rt())x->fa->ch[x->tp()]=this;
		x->ch[k]=ch[!k];if(ch[!k])ch[!k]->fa=x;
		ch[!k]=x;x->fa=this;
	}
	void splay()
	{
		for(;!rt();rotate())if(!fa->rt())(fa->tp()==tp()?fa->rotate():rotate());
	}
}nn[200100];
int dep[200100],p[200100],q[200100],xx[200100],yy[200100],ans[200100];
struct par{int x,y,no;}pp[200100];
inline bool cmp(const par&A,const par&B){return A.y==B.y?A.x<B.x:A.y<B.y;}
int access(re int a,re int t)
{
	re nd*x=&nn[a],*y=0;
	for(;x!=(&nn[0]);x=x->fa)
	{
		x->splay();
		if(x->v+2*dep[x-nn]>t)break;
		if(x->ch[1])x->ch[1]->v=x->v;x->ch[1]=y;y=x;
	}
	if(y)y->v=t-dep[x-nn]*2;
	return t-dep[x-nn]*2+dep[a];
}
int main()
{
	re int n,m;
	scanf("%d%d",&n,&m);
	for(re int i=1;i<=n;i++)scanf("%d",&p[i]),dep[i]=dep[p[i]]+1,nn[i].v=-1e9,nn[i].fa=&nn[p[i]];
	for(re int i=1;i<=m;i++)
	{
		scanf("%d%d",&xx[i],&yy[i]);
		pp[i]=(par){xx[i],yy[i]+dep[xx[i]],i};
	}
	sort(pp+1,pp+m+1,cmp);
	for(re int i=1;i<=m;i++)
	{
		ans[pp[i].no]=access(pp[i].x,pp[i].y);
	}
	for(re int i=1;i<=m;i++)printf("%d ",ans[i]);
}


#include<bits/stdc++.h>
using namespace std;
#define re register
struct nd
{
	int v;
	nd*ch[2],*fa;
	bool rt(){return (!fa)||(fa->ch[0]!=this&&fa->ch[1]!=this);}
	bool tp(){return fa->ch[1]==this;}
	void rotate()
	{
		re bool k=tp();re nd*x=fa;v=x->v;
		fa=x->fa;if(!x->rt())x->fa->ch[x->tp()]=this;
		x->ch[k]=ch[!k];if(ch[!k])ch[!k]->fa=x;
		ch[!k]=x;x->fa=this;
	}
	void splay()
	{
		for(;!rt();rotate())if(!fa->rt())(fa->tp()==tp()?fa->rotate():rotate());
	}
}nn[200100];
int dep[200100],p[200100],q[200100],xx[200100],yy[200100],ans[200100];
struct par{int x,y,no;}pp[200100];
inline bool cmp(const par&A,const par&B){return A.y==B.y?A.x<B.x:A.y<B.y;}
int access(re int a,re int t)
{
	re nd*x=&nn[a],*y=0;
	for(;x!=(&nn[0]);x=x->fa)
	{
		x->splay();
		if(x->v+2*dep[x-nn]>t)break;
		x->ch[1]=y;y=x;
	}
	if(y)y->v=t-dep[x-nn]*2;
	return t-dep[x-nn]*2+dep[a];
}
int main()
{
	re int n,m;
	scanf("%d%d",&n,&m);
	for(re int i=1;i<=n;i++)scanf("%d",&p[i]),dep[i]=dep[p[i]]+1,nn[i].v=-1e9,nn[i].fa=&nn[p[i]];
	for(re int i=1;i<=m;i++)
	{
		scanf("%d%d",&xx[i],&yy[i]);
		pp[i]=(par){xx[i],yy[i]+dep[xx[i]],i};
	}
	sort(pp+1,pp+m+1,cmp);
	for(re int i=1;i<=m;i++)
	{
		ans[pp[i].no]=access(pp[i].x,pp[i].y);
	}
	for(re int i=1;i<=m;i++)printf("%d ",ans[i]);
}


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

int n,m,head[200010],nxt[400010],b[400010],k,dep[200010],size[200010],son[200010],top[200010],dfn[200010],now,fa[200010],down[200010],ord[200010];
void push(int s,int t){
	nxt[++k]=head[s];
	head[s]=k;
	b[k]=t;
}
void dfs1(int x,int f){
	size[x]=1;
	fa[x]=f;
	for(int i=head[x];i;i=nxt[i])
		if(b[i]!=f){
			dep[b[i]]=dep[x]+1;
			dfs1(b[i],x);
			size[x]+=size[b[i]];
			if(size[b[i]]>size[son[x]])son[x]=b[i];
		}
}
void dfs2(int x,int t){
	dfn[x]=++now;
	ord[now]=x;
	top[x]=t;
	if(son[x])dfs2(son[x],t);
	for(int i=head[x];i;i=nxt[i])
		if(b[i]!=fa[x]&&b[i]!=son[x])
			dfs2(b[i],b[i]);
	down[x]=(son[x])?down[son[x]]:dfn[x];
}
int LCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
		else y=fa[top[y]];
	}
	return dep[x]<dep[y]?x:y;
}
struct point{
	int ord,t,x,T;
}num[200010];
struct segtree{
	int se[2000010],lazy[2000010];
	void pushup(int root){
		se[root]=std::max(se[root<<1],se[root<<1|1]);
	}
	void pushdown(int x,int y){
		se[x]=std::max(se[x],y);
		lazy[x]=std::max(lazy[x],y);
	}
	void spread(int x){
		pushdown(x<<1,lazy[x]);
		pushdown(x<<1|1,lazy[x]);
		lazy[x]=-0x7f7f7f7f;
	}
	void build(int root,int l,int r){
		memset(se,-0x7f7f7f7f,sizeof se);
		memset(lazy,-0x7f7f7f7f,sizeof lazy);
	}
	void set(int root,int l,int r,int e,int x){
		spread(root);
		if(l==r){
			se[root]=std::max(se[root],x);
			return;
		}
		if((l+r)>>1>=e)set(root<<1,l,(l+r)>>1,e,x);
		else set(root<<1|1,((l+r)>>1)+1,r,e,x);
		pushup(root);
	}
	int get(int root,int l,int r,int el,int er,int x){
//		printf("get %d %d %d\n",root,l,r);
		spread(root);
		if(el>r||er<l)return -1;
		if(l==r){
			if(se[root]>x)return l;
			else return -1;
		}
		if(el<=l&&er>=r){
			if(se[root<<1|1]>x)return get(root<<1|1,((l+r)>>1)+1,r,el,er,x);
			else return get(root<<1,l,(l+r)>>1,el,er,x);
		}
		int tem=get(root<<1|1,((l+r)>>1)+1,r,el,er,x);
		if(!~tem)return get(root<<1,l,(l+r)>>1,el,er,x);
		else return tem;
	}
	void update(int root,int l,int r,int el,int er,int x){
		if(el>r||er<l)return;
		if(el<=l&&er>=r){
			pushdown(root,x);
			return;
		}
		spread(root);
		update(root<<1,l,(l+r)>>1,el,er,x);
		update(root<<1|1,((l+r)>>1)+1,r,el,er,x);
		pushup(root);
	}
	int query(int root,int l,int r,int e){
		spread(root);
//		printf("%d %d %d %d\n",root,l,r,se[root]);
		if(l==r){
			return se[root];
		}
		if((l+r)>>1>=e)return query(root<<1,l,(l+r)>>1,e);
		else return query(root<<1|1,((l+r)>>1)+1,r,e);
	}
}s1,s2;
int ans[200010];
bool cmp(point a,point b){return a.T<b.T||(a.T==b.T&&a.x<b.x);}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,tem;i<=n;i++){
		scanf("%d",&tem);
		push(tem?tem:(n+1),i);
	}
	dfs1(n+1,0);
	dfs2(n+1,n+1);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&num[i].x,&num[i].t);
		num[i].ord=i;
		num[i].T=num[i].t+dep[num[i].x];
	}
	s1.build(1,1,n);
	s2.build(1,1,n);
	std::sort(num+1,num+m+1,cmp);
	for(int i=1;i<=m;i++){
		int y=num[i].x;
		while(y){
			if(s1.query(1,1,n,dfn[y])>num[i].T-(dep[y]<<1))break;
			int tem=s2.get(1,1,n,dfn[top[y]],dfn[y]-1,num[i].T);
			if(~tem){
				y=ord[tem];
				break;
			}
			y=fa[top[y]];
		}
		if(!y)y=n+1;
//		printf("%d %d\n",num[i].x,y);
		ans[num[i].ord]=num[i].t+((dep[num[i].x]-dep[y])<<1);
		int x=num[i].x;
		while(x){
			s1.update(1,1,n,std::max(dfn[y],dfn[top[x]]),dfn[x],num[i].T-(dep[y]<<1));
			s2.set(1,1,n,dfn[x],num[i].T+((dep[x]-dep[y])<<1));
//			printf("%d\n",num[i].T+((dep[x]-dep[y])<<1));
			x=fa[top[x]];
			if(dep[x]<dep[y])break;
		}
	}
	for(int i=1;i<=m;i++)printf("%d ",ans[i]);
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
int n,m,head[200010],nxt[400010],b[400010],k,dep[200010],size[200010],son[200010],top[200010],dfn[200010],now,fa[200010],down[200010],ord[200010];
void push(int s,int t){
nxt[++k]=head[s];
head[s]=k;
b[k]=t;
}
void dfs1(int x,int f){
size[x]=1;
fa[x]=f;
for(int i=head[x];i;i=nxt[i])
if(b[i]!=f){
dep[b[i]]=dep[x]+1;
dfs1(b[i],x);
size[x]+=size[b[i]];
if(size[b[i]]>size[son[x]])son[x]=b[i];
}
}
void dfs2(int x,int t){
dfn[x]=++now;
ord[now]=x;
top[x]=t;
if(son[x])dfs2(son[x],t);
for(int i=head[x];i;i=nxt[i])
if(b[i]!=fa[x]&&b[i]!=son[x])
dfs2(b[i],b[i]);
down[x]=(son[x])?down[son[x]]:dfn[x];
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
else y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
struct point{
int ord,t,x,T;
}num[200010];
struct segtree{
int se[2000010],lazy[2000010];
void pushup(int root){
se[root]=std::max(se[root<<1],se[root<<1|1]);
}
void pushdown(int x,int y){
se[x]=std::max(se[x],y);
lazy[x]=std::max(lazy[x],y);
}
void spread(int x){
pushdown(x<<1,lazy[x]);
pushdown(x<<1|1,lazy[x]);
lazy[x]=-0x7f7f7f7f;
}
void build(int root,int l,int r){
memset(se,-0x7f7f7f7f,sizeof se);
memset(lazy,-0x7f7f7f7f,sizeof lazy);
}
void set(int root,int l,int r,int e,int x){
spread(root);
if(l==r){
se[root]=std::max(se[root],x);
return;
}
if((l+r)>>1>=e)set(root<<1,l,(l+r)>>1,e,x);
else set(root<<1|1,((l+r)>>1)+1,r,e,x);
pushup(root);
}
int get(int root,int l,int r,int el,int er,int x){
// printf("get %d %d %d\n",root,l,r);
spread(root);
if(el>r||er<l)return -1;
if(l==r){
if(se[root]>x)return l;
else return -1;
}
if(el<=l&&er>=r){
if(se[root<<1|1]>x)return get(root<<1|1,((l+r)>>1)+1,r,el,er,x);
else return get(root<<1,l,(l+r)>>1,el,er,x);
}
int tem=get(root<<1|1,((l+r)>>1)+1,r,el,er,x);
if(!~tem)return get(root<<1,l,(l+r)>>1,el,er,x);
else return tem;
}
void update(int root,int l,int r,int el,int er,int x){
// if(root==1)printf("update %d %d %d %d\n",root,el,er,x);
if(el>r||er<l)return;
if(el<=l&&er>=r){
// printf("%d %d\n",l,r);
pushdown(root,x);
return;
}
spread(root);
update(root<<1,l,(l+r)>>1,el,er,x);
update(root<<1|1,((l+r)>>1)+1,r,el,er,x);
pushup(root);
}
int query(int root,int l,int r,int e){
// if(root==1)printf("query %d\n",e);
spread(root);
if(l==r){
// printf("%d %d\n",l,r);
return se[root];
}
if((l+r)>>1>=e)return query(root<<1,l,(l+r)>>1,e);
else return query(root<<1|1,((l+r)>>1)+1,r,e);
}
}s1,s2;
int ans[200010];
bool cmp(point a,point b){return a.T<b.T||(a.T==b.T&&a.x<b.x);}
int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1,tem;i<=n;i++){
scanf("%d",&tem);
push(tem?tem:(n+1),i);
}
++n;
dfs1(n,0);
dfs2(n,n);
for(int i=1;i<=m;i++){
scanf("%d%d",&num[i].x,&num[i].t);
num[i].ord=i;
num[i].T=num[i].t+dep[num[i].x];
}
s1.build(1,1,n);
s2.build(1,1,n);
std::sort(num+1,num+m+1,cmp);
for(int i=1;i<=m;i++){
int y=num[i].x;
while(y){
if(s1.query(1,1,n,dfn[y])>num[i].T-(dep[y]<<1))break;
int tem=s2.get(1,1,n,dfn[top[y]],dfn[y]-1,num[i].T);
if(~tem){
y=ord[tem];
break;
}
y=fa[top[y]];
}
if(!y)y=n+1;
// printf("%d %d\n",num[i].x,y);
ans[num[i].ord]=num[i].t+((dep[num[i].x]-dep[y])<<1);
int x=num[i].x;
while(x){
s1.update(1,1,n,std::max(dfn[y],dfn[top[x]]),dfn[x],num[i].T-(dep[y]<<1));
s2.set(1,1,n,dfn[x],num[i].T+((dep[x]-dep[y])<<1));
// printf("%d\n",num[i].T+((dep[x]-dep[y])<<1));
x=fa[top[x]];
if(dep[x]<dep[y])break;
}
}
for(int i=1;i<=m;i++)printf("%d ",ans[i]);
}


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

int n,m,head[200010],nxt[400010],b[400010],k,dep[200010],size[200010],son[200010],top[200010],dfn[200010],now,fa[200010],down[200010],ord[200010];
void push(int s,int t){
	nxt[++k]=head[s];
	head[s]=k;
	b[k]=t;
}
void dfs1(int x,int f){
	size[x]=1;
	fa[x]=f;
	for(int i=head[x];i;i=nxt[i])
		if(b[i]!=f){
			dep[b[i]]=dep[x]+1;
			dfs1(b[i],x);
			size[x]+=size[b[i]];
			if(size[b[i]]>size[son[x]])son[x]=b[i];
		}
}
void dfs2(int x,int t){
	dfn[x]=++now;
	ord[now]=x;
	top[x]=t;
	if(son[x])dfs2(son[x],t);
	for(int i=head[x];i;i=nxt[i])
		if(b[i]!=fa[x]&&b[i]!=son[x])
			dfs2(b[i],b[i]);
	down[x]=(son[x])?down[son[x]]:dfn[x];
}
int LCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
		else y=fa[top[y]];
	}
	return dep[x]<dep[y]?x:y;
}
struct point{
	int ord,t,x,T;
}num[200010];
struct segtree{
	int se[2000010],lazy[2000010];
	void pushup(int root){
		se[root]=std::max(se[root<<1],se[root<<1|1]);
	}
	void pushdown(int x,int y){
		se[x]=std::max(se[x],y);
		lazy[x]=std::max(lazy[x],y);
	}
	void spread(int x){
		pushdown(x<<1,lazy[x]);
		pushdown(x<<1|1,lazy[x]);
		lazy[x]=-0x7f7f7f7f;
	}
	void build(int root,int l,int r){
		memset(se,-0x7f7f7f7f,sizeof se);
		memset(lazy,-0x7f7f7f7f,sizeof lazy);
	}
	void set(int root,int l,int r,int e,int x){
		spread(root);
		if(l==r){
			se[root]=std::max(se[root],x);
			return;
		}
		if((l+r)>>1>=e)set(root<<1,l,(l+r)>>1,e,x);
		else set(root<<1|1,((l+r)>>1)+1,r,e,x);
		pushup(root);
	}
	int get(int root,int l,int r,int el,int er,int x){
//		printf("get %d %d %d\n",root,l,r);
		spread(root);
		if(el>r||er<l)return -1;
		if(l==r){
			if(se[root]>x)return l;
			else return -1;
		}
		if(el<=l&&er>=r){
			if(se[root<<1|1]>x)return get(root<<1|1,((l+r)>>1)+1,r,el,er,x);
			else return get(root<<1,l,(l+r)>>1,el,er,x);
		}
		int tem=get(root<<1|1,((l+r)>>1)+1,r,el,er,x);
		if(!~tem)return get(root<<1,l,(l+r)>>1,el,er,x);
		else return tem;
	}
	void update(int root,int l,int r,int el,int er,int x){
//		if(root==1)printf("update %d %d %d %d\n",root,el,er,x);
		if(el>r||er<l)return;
		if(el<=l&&er>=r){
//			printf("%d %d\n",l,r);
			pushdown(root,x);
			return;
		}
		spread(root);
		update(root<<1,l,(l+r)>>1,el,er,x);
		update(root<<1|1,((l+r)>>1)+1,r,el,er,x);
		pushup(root);
	}
	int query(int root,int l,int r,int e){
//		if(root==1)printf("query %d\n",e);
		spread(root);
		if(l==r){
//			printf("%d %d\n",l,r);
			return se[root];
		}
		if((l+r)>>1>=e)return query(root<<1,l,(l+r)>>1,e);
		else return query(root<<1|1,((l+r)>>1)+1,r,e);
	}
}s1,s2;
int ans[200010];
bool cmp(point a,point b){return a.T<b.T||(a.T==b.T&&a.x<b.x);}
int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1,tem;i<=n;i++){
		scanf("%d",&tem);
		push(tem?tem:(n+1),i);
	}
	++n;
	dfs1(n,0);
	dfs2(n,n);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&num[i].x,&num[i].t);
		num[i].ord=i;
		num[i].T=num[i].t+dep[num[i].x];
	}
	s1.build(1,1,n);
	s2.build(1,1,n);
	std::sort(num+1,num+m+1,cmp);
	for(int i=1;i<=m;i++){
		int y=num[i].x;
		while(y){
			if(s1.query(1,1,n,dfn[y])>num[i].T-(dep[y]<<1))break;
			int tem=s2.get(1,1,n,dfn[top[y]],dfn[y]-1,num[i].T);
			if(~tem){
				y=ord[tem];
				break;
			}
			y=fa[top[y]];
		}
		if(!y)y=n+1;
//		printf("%d %d\n",num[i].x,y);
		ans[num[i].ord]=num[i].t+((dep[num[i].x]-dep[y])<<1);
		int x=num[i].x;
		while(x){
			s1.update(1,1,n,std::max(dfn[y],dfn[top[x]]),dfn[x],num[i].T-(dep[y]<<1));
			s2.set(1,1,n,dfn[x],num[i].T+((dep[x]-dep[y])<<1));
//			printf("%d\n",num[i].T+((dep[x]-dep[y])<<1));
			x=fa[top[x]];
			if(dep[x]<dep[y])break;
		}
	}
	for(int i=1;i<=m;i++)printf("%d ",ans[i]);
}


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

int n,m,head[200010],nxt[400010],b[400010],k,dep[200010],size[200010],son[200010],top[200010],dfn[200010],now,fa[200010],down[200010],ord[200010];
void push(int s,int t){
	nxt[++k]=head[s];
	head[s]=k;
	b[k]=t;
}
void dfs1(int x,int f){
	size[x]=1;
	fa[x]=f;
	for(int i=head[x];i;i=nxt[i])
		if(b[i]!=f){
			dep[b[i]]=dep[x]+1;
			dfs1(b[i],x);
			size[x]+=size[b[i]];
			if(size[b[i]]>size[son[x]])son[x]=b[i];
		}
}
void dfs2(int x,int t){
	dfn[x]=++now;
	ord[now]=x;
	top[x]=t;
	if(son[x])dfs2(son[x],t);
	for(int i=head[x];i;i=nxt[i])
		if(b[i]!=fa[x]&&b[i]!=son[x])
			dfs2(b[i],b[i]);
	down[x]=(son[x])?down[son[x]]:dfn[x];
}
int LCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
		else y=fa[top[y]];
	}
	return dep[x]<dep[y]?x:y;
}
struct point{
	int ord,t,x,T;
}num[200010];
struct segtree{
	int se[2000010],lazy[2000010];
	void pushup(int root){
		se[root]=std::max(se[root<<1],se[root<<1|1]);
	}
	void pushdown(int x,int y){
		se[x]=std::max(se[x],y);
		lazy[x]=std::max(lazy[x],y);
	}
	void spread(int x){
		pushdown(x<<1,lazy[x]);
		pushdown(x<<1|1,lazy[x]);
		lazy[x]=-0x7f7f7f7f;
	}
	void build(int root,int l,int r){
		memset(se,-0x7f7f7f7f,sizeof se);
		memset(lazy,-0x7f7f7f7f,sizeof lazy);
	}
	void set(int root,int l,int r,int e,int x){
		spread(root);
		if(l==r){
			se[root]=std::max(se[root],x);
			return;
		}
		if((l+r)>>1>=e)set(root<<1,l,(l+r)>>1,e,x);
		else set(root<<1|1,((l+r)>>1)+1,r,e,x);
		pushup(root);
	}
	int get(int root,int l,int r,int el,int er,int x){
//		printf("get %d %d %d\n",root,l,r);
		spread(root);
		if(el>r||er<l)return -1;
		if(l==r){
			if(se[root]>x)return l;
			else return -1;
		}
		if(el<=l&&er>=r){
			if(se[root<<1]>x)return get(root<<1,l,(l+r)>>1,el,er,x);
			else return get(root<<1|1,((l+r)>>1)+1,r,el,er,x);
		}
		int tem=get(root<<1,l,(l+r)>>1,el,er,x);
		if(!~tem)return get(root<<1|1,((l+r)>>1)+1,r,el,er,x);
		else return tem;
	}
	void update(int root,int l,int r,int el,int er,int x){
		if(el>r||er<l)return;
		if(el<=l&&er>=r){
			pushdown(root,x);
			return;
		}
		spread(root);
		update(root<<1,l,(l+r)>>1,el,er,x);
		update(root<<1|1,((l+r)>>1)+1,r,el,er,x);
		pushup(root);
	}
	int query(int root,int l,int r,int e){
		spread(root);
//		printf("%d %d %d %d\n",root,l,r,se[root]);
		if(l==r){
			return se[root];
		}
		if((l+r)>>1>=e)return query(root<<1,l,(l+r)>>1,e);
		else return query(root<<1|1,((l+r)>>1)+1,r,e);
	}
}s1,s2;
int ans[200010];
bool cmp(point a,point b){return a.T<b.T||(a.T==b.T&&a.x<b.x);}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,tem;i<=n;i++){
		scanf("%d",&tem);
		push(tem?tem:(n+1),i);
	}
	dfs1(n+1,0);
	dfs2(n+1,n+1);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&num[i].x,&num[i].t);
		num[i].ord=i;
		num[i].T=num[i].t+dep[num[i].x];
	}
	s1.build(1,1,n);
	s2.build(1,1,n);
	std::sort(num+1,num+m+1,cmp);
	for(int i=1;i<=m;i++){
		int y=num[i].x;
		while(y){
			if(s1.query(1,1,n,dfn[y])>num[i].T-(dep[y]<<1))break;
			int tem=s2.get(1,1,n,dfn[top[y]],dfn[y]-1,num[i].T);
			if(~tem){
				y=ord[tem];
				break;
			}
			y=fa[top[y]];
		}
		if(!y)y=n+1;
//		printf("%d %d\n",num[i].x,y);
		ans[num[i].ord]=num[i].t+((dep[num[i].x]-dep[y])<<1);
		int x=num[i].x;
		while(x){
			s1.update(1,1,n,std::max(dfn[y],dfn[top[x]]),dfn[x],num[i].T-(dep[y]<<1));
			s2.set(1,1,n,dfn[x],num[i].T+((dep[x]-dep[y])<<1));
			x=fa[top[x]];
			if(dep[x]<dep[y])break;
		}
	}
	for(int i=1;i<=m;i++)printf("%d ",ans[i]);
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200005,inf=0x3f3f3f3f;
int read(){
	int f=1,g=0;
	char ch=getchar();
	for (;!isdigit(ch);ch=getchar()) if (ch=='-') f=-1;
	for (;isdigit(ch);ch=getchar()) g=g*10+ch-'0';
	return f*g;
}
int n,m,siz,fir[N],ans[N];
struct edge{int u,v,nex;}e[N*2];
void add(int u,int v){e[++siz]=(edge){u,v,fir[u]};fir[u]=siz;}
int cnt,b[N],size[N],depth[N],hs[N],fa[N][20],bel[N];
int ccnt,chtop[N],ord[N];
void build(int x){
	size[x]=1;depth[x]=depth[fa[x][0]]+1;hs[x]=0;
	for (int i=1;i<20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
	for (int i=fir[x];i;i=e[i].nex){
		build(e[i].v);
		size[x]+=size[e[i].v];
		if (size[e[i].v]>size[hs[x]]) hs[x]=e[i].v;
	}
}
void build2(int x){
	bel[x]=ccnt;b[x]=++cnt;ord[cnt]=x;
	if (hs[x]) build2(hs[x]);
	else return;
	for (int i=fir[x];i;i=e[i].nex)
	if (e[i].v!=hs[x]){
		chtop[++ccnt]=e[i].v;
		build2(e[i].v);
	}
}
int goup(int x,int dep){
	for (int i=19;i>=0;i--) if (depth[fa[x][i]]>=dep) x=fa[x][i];
	return x;
}
int lca(int x,int y){
	if (depth[x]>depth[y]) swap(x,y);
	for (int i=19;i>=0;i--) if (depth[fa[y][i]]>=depth[x]) y=fa[y][i];
	if (x==y) return x;
	for (int i=19;i>=0;i--)
	if (fa[y][i]!=fa[x][i]) {x=fa[x][i];y=fa[y][i];}
	return fa[x][0];
}
struct segment_tree{
	int rb[N<<2],tag[N<<2],f[N<<2];
	void down(int x){
		int lc=x<<1,rc=lc+1;
		f[lc]=max(f[lc],2*rb[lc]+tag[x]);
		f[rc]=max(f[rc],2*rb[rc]+tag[x]);
		tag[lc]=max(tag[lc],tag[x]);
		tag[rc]=max(tag[rc],tag[x]);
	}
	void check(int x){f[x]=max(f[x*2],f[x*2+1]);}
	void build(int x,int l,int r){
		tag[x]=-inf;f[x]=2*r+tag[x];rb[x]=r;
		if (l==r) return;
		int mid=(l+r)>>1;
		build(x*2,l,mid);
		build(x*2+1,mid+1,r);
	}
	void modi(int x,int l,int r,int &fl,int &fr,int &t){
		if ((fl<=l)&&(fr>=r)){tag[x]=max(tag[x],t);f[x]=max(f[x],t+2*rb[x]);return;}
		down(x);
		int mid=(l+r)>>1;
		if (fl<=mid) modi(x*2,l,mid,fl,fr,t);
		if (fr>mid) modi(x*2+1,mid+1,r,fl,fr,t);
		check(x);
	}
	int que(int x,int l,int r,int &fl,int &fr,int &t){
		if (f[x]<=t) return -1;
		if (l==r) return l;
		down(x);
		int mid=(l+r)>>1,ans=-1;
		if (fr>mid) ans=que(x*2+1,mid+1,r,fl,fr,t);
		if (ans>=0) return ans;
		if (fl<=mid) return que(x*2,l,mid,fl,fr,t);
		return -1;
	}
	void modify(int l,int r,int t){if (l<=r) modi(1,1,n,l,r,t);}
	int query(int l,int r,int t){
		if (l<=r) return que(1,1,n,l,r,t);
		else return -1;
	}
}f;
int quet(int x,int y,int s){
	int t=f.query(b[x],b[y],s);
	if (t<0) return t;
	return ord[t];
}
void modify(int x,int y,int st,int t){
	t+=2*depth[y]-depth[st]-2*b[y];
	f.modify(b[y],b[x],t);
}
int get_first(int x,int t){
	int s=depth[x]+t;
	while (x!=0){
		int y=chtop[bel[x]],c=quet(y,x,s);
		if (c!=-1) return c;
		x=fa[y][0];
	}
	return 0;
}
int query(int x,int t){
	int y=get_first(x,t);
	t+=depth[x]-depth[y];
	int ans=t+depth[x]-depth[y];
	while (bel[x]!=bel[y]){
		int z=chtop[bel[x]];
		modify(x,z,y,t);
		x=fa[z][0];
	}
	if (x!=y){
		int z=goup(x,depth[y]+1);
		modify(x,z,y,t);
	}
	return ans;
}
struct quer{int t,pos,i;} q[N];
bool cmp(quer x,quer y){return (x.t+depth[x.pos]!=y.t+depth[y.pos]) ? (x.t+depth[x.pos]<y.t+depth[y.pos]) : (x.pos<y.pos);}
int main(){
	n=read();m=read();
	for (int i=1;i<=n;i++){
		fa[i][0]=read();
		add(fa[i][0],i);
	}
	for (int i=1;i<=n;i++) if (fa[i][0]==0) build(i);
	for (int i=1;i<=n;i++)
	if (fa[i][0]==0) {chtop[++ccnt]=i;build2(i);}
	for (int i=1;i<=m;i++){
		q[i].pos=read();q[i].t=read();
		q[i].i=i;
	}
	f.build(1,1,n);
	sort(q+1,q+m+1,cmp);
	for (int i=1;i<=m;i++)
		ans[q[i].i]=query(q[i].pos,q[i].t);
	for (int i=1;i<=m;i++) printf("%d ",ans[i]);
	printf("\n");
	return 0;
}


#include<stdio.h>
#include<cstring>
#include<algorithm>
#define ll long long
#define md ((l+r)>>1)
using namespace std;
const int N=200100,oo=2e9;
inline int read(){
	int x=0,c=getchar(),f=0;
	for(;c>'9'||c<'0';f=c=='-',c=getchar());
	for(;c>='0'&&c<='9';c=getchar())
	x=(x<<1)+(x<<3)+c-'0';return f?-x:x;
}
inline void write(ll x){
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
int n,m,fa[N],L,h[N],ne[N],to[N];
void addl(int x,int y){
	ne[++L]=h[x];h[x]=L;to[L]=y;
}
int lv[N],sz[N],son[N],top[N],len[N],ti,dfn[N],id[N];
void dfs(int x){
	lv[x]=lv[fa[x]]+1;sz[x]=1;
	for(int y,k=h[x];k;k=ne[k]){
		dfs(y=to[k]);sz[x]+=sz[y];
		if(sz[y]>sz[son[x]])son[x]=y;
	}
}
void dfs(int x,int tp){
	dfn[x]=++ti;id[ti]=x;
	top[x]=tp;len[tp]++;
	if(son[x]<=n)dfs(son[x],tp);
	for(int k=h[x];k;k=ne[k])
	if(to[k]!=son[x])dfs(to[k],to[k]);
}
struct cqz{int x,t,i;}q[N];
inline bool operator<(cqz i,cqz j){
	if(i.t+lv[i.x]==j.t+lv[j.x])return i.x<j.x;
	else return i.t+lv[i.x]<j.t+lv[j.x];
}
struct seg{
	int tu,ps;
}tr[N*4];
int ls[N*4],rs[N*4],cv[N*4],sm,rt[N],ans[N];
void build(int&i,int l,int r){
	i=++sm;tr[i].ps=r;tr[i].tu=-1;cv[i]=-oo;
	if(l==r)return;build(ls[i],l,md);build(rs[i],md+1,r);
}
void down(int i,int l,int r);
seg max(seg x,seg y){
	if(x.tu-(y.ps-x.ps)>y.tu)return x;
	else return y;
}
void cov(int i,int l,int r,int x,int y,int k){
	if(l>=x&&r<=y){
		cv[i]=k;
		tr[i].ps=r;
		tr[i].tu=k+r;
		return;
	}down(i,l,r);
	if(x<=md)cov(ls[i],l,md,x,y,k);
	if(y>md)cov(rs[i],md+1,r,x,y,k);
	tr[i]=max(tr[ls[i]],tr[rs[i]]);
}
void down(int i,int l,int r){
	if(cv[i]==-oo)return;
	cov(ls[i],l,md,l,md,cv[i]);
	cov(rs[i],md+1,r,md+1,r,cv[i]);
	cv[i]=-oo;
}
bool can(seg&w,int x,int t){
	t+=x-w.ps;
	return w.tu>t;
}
int get(int i,int l,int r,int x,int t){
	if(l>x)return 0;
	if(!can(tr[i],x,t))return 0;
	if(l==r)return l;
	down(i,l,r);
	int re=get(rs[i],md+1,r,x,t);
	if(re)return re;
	return get(ls[i],l,md,x,t);
}
void solve(int X,int T,int I){
	int x,y,t,p,r;
	for(x=X,t=T;x>=0;x=fa[y]){
		y=top[x];
		p=lv[x]-lv[y]+1;
		r=get(rt[y],1,len[y],p,t);
		if(r){r=id[dfn[y]+r-1];break;}
		t+=p;
	}
	t=T+lv[X]+lv[X]-lv[r]-lv[r];
	ans[I]=t;
	for(x=X;top[x]!=top[r];x=fa[y]){
		y=top[x];
		p=lv[x]-lv[y]+1;
		t-=p;
		cov(rt[y],1,len[y],1,p,t);
	}
	y=top[x];
	r=lv[r]-lv[y]+1;
	p=lv[x]-lv[y]+1;
	t-=p;
	if(r<p)cov(rt[y],1,len[y],r+1,p,t);
}
int main(){
	register int i;
	n=read();m=read();
	fa[0]=-1;
	for(i=1;i<=n;i++)fa[i]=read(),addl(fa[i],i);
	for(i=0;i<=n;i++)son[i]=n+1;
	dfs(0);dfs(0,0);
	for(i=0;i<=n;i++)if(top[i]==i)build(rt[i],1,len[i]);
	cov(rt[0],1,len[0],1,1,oo);
	for(i=1;i<=m;i++)q[i].x=read(),q[i].t=read(),q[i].i=i;
	sort(q+1,q+m+1);
	for(i=1;i<=m;i++)solve(q[i].x,q[i].t,q[i].i);
	for(i=1;i<m;i++)printf("%d ",ans[i]);printf("%d\n",ans[m]);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x = 0,f = 1;char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-')f = -1;ch = getchar();}
	while(ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch = getchar();}
	return x*f;
}
void write(int x){
	if(x > 9) write(x/10);
	putchar(x%10+'0');
}

const int N = 200005,inf = 1e9;
int a[N],t[N],id[N],fa[N],dep[N],num[N],son[N],q[N],dfn[N];
int top[N],ans[N],n,m,cnt = 0,fd;
struct tree{ int mx,lazy; }tr[N<<2];
bool cmp(int x,int y){
	if(t[x]+dep[a[x]] != t[y]+dep[a[y]])
		return t[x]+dep[a[x]] < t[y]+dep[a[y]];
	return a[x] < a[y];
}
inline void pushup(int x){ tr[x].mx = max(tr[x<<1].mx,tr[x<<1|1].mx); }
inline void pushdown(int x,int l,int mid,int r){
	if(tr[x].lazy < -inf) return;
	tr[x<<1].lazy = tr[x<<1|1].lazy = tr[x].lazy;
	tr[x<<1].mx = mid*2+tr[x].lazy;
	tr[x<<1|1].mx = r*2+tr[x].lazy;
	tr[x].lazy = -inf-1;
}
void modify(int now,int l,int r,int x,int y,int z){
	if(x <= l && r <= y){
		tr[now].lazy = z; tr[now].mx = r*2+z;
		return;
	}
	int mid = (l+r)>>1;
	pushdown(now,l,mid,r);
	if(x <= mid) modify(now<<1,l,mid,x,y,z);
	if(y > mid) modify(now<<1|1,mid+1,r,x,y,z);
	pushup(now);
}
void query(int now,int l,int r,int x,int y,int z){
	if(tr[now].mx <= z) return;
	if(l == r){fd = q[l];return;}
	int mid = (l+r)>>1;
	pushdown(now,l,mid,r);
	if(fd == -1 && y > mid) query(now<<1|1,mid+1,r,x,y,z);
	if(fd == -1 && x <= mid) query(now<<1,l,mid,x,y,z);
	pushup(now);
}
int work(int x,int t){
	int y = x;
	while(1){
		fd = -1;
		query(1,0,n,dfn[top[y]],dfn[y],t+dfn[y]);
		if(fd >= 0){
			t += dep[y]-dep[fd];
			y = fd;
			break;
		}
		if(!y) break;
		t += dep[y]-dep[fa[top[y]]];
		y = fa[top[y]];
	}
	int z = t+dep[x]-dep[y];
	while(1){
		if(top[x] == top[y]){
			if(x != y) modify(1,0,n,dfn[y]+1,dfn[x],t-dfn[y]);
			break;
		}
		modify(1,0,n,dfn[top[x]],dfn[x],dep[x]-dep[y]+t-dfn[x]);
		x = fa[top[x]];
	}
	return z;
}

int main(){
	n = read(); m = read();
	for(int i = 1;i <= n;++i){
		fa[i] = read();
		dep[i] = dep[fa[i]]+1;
		num[i] = 1;
	}
	for(int i = n;i;i--){
		if(num[i] > num[son[fa[i]]]) son[fa[i]] = i;
		if(fa[i]) num[fa[i]] += num[i];
	}
	for(int i = son[0];i;i = son[i]) q[dfn[i] = ++cnt] = i;
	for(int i = 0;i <= n;++i)
		if(!dfn[i])
			for(int j = i;j;j = son[j])
				top[q[dfn[j] = ++cnt] = j] = i;
	for(int i = 1;i <= m;++i) a[i] = read(),t[i] = read();
	for(int i = 1;i <= m;++i) id[i] = i;
	sort(id+1,id+m+1,cmp);
	tr[1].mx = tr[1].lazy = -inf;
	for(int i = 1;i <= m;++i)
		ans[id[i]] = work(a[id[i]],t[id[i]]);
	for(int i = 1;i <= m;++i) write(ans[i]),putchar(' ');
	puts("");
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N=2e5+5,INF=1e9+N*10;
struct Tree{int sum,add;}t[N<<2];
struct Que{int x,t;}q[N];
int n,m,siz[N],son[N],top[N],fa[N],dep[N];
int ord[N],dfn[N],ids,w[N],id[N];
vector<int> G[N];

void dfs1(int u)
{
	siz[u]=1;
	for(int i=0,v;i<G[u].size();++i)
	{
		dep[v=G[u][i]]=dep[u]+1;
		dfs1(v); siz[u]+=siz[v];
		if(!son[u]||siz[v]>siz[son[u]]) son[u]=v;
	}
}

void dfs2(int u,int tp)
{
	top[u]=tp,dfn[u]=++ids,w[ids]=u;
	if(son[u]) dfs2(son[u],tp);
	for(int i=0,v;i<G[u].size();++i)
		if((v=G[u][i])!=son[u]) dfs2(v,v);
}

inline void pushdown(int rt,int l,int r)
{
	int mid=l+r>>1;
	t[rt<<1].add=max(t[rt<<1].add,t[rt].add);
	t[rt<<1].sum=max(t[rt<<1].sum,t[rt<<1].add+2*dep[w[mid]]);
	t[rt<<1|1].add=max(t[rt<<1|1].add,t[rt].add);
	t[rt<<1|1].sum=max(t[rt<<1|1].sum,t[rt<<1|1].add+2*dep[w[r]]);
}

void build(int rt,int l,int r)
{
	t[rt].add=-INF;
	if(l==r) {t[rt].sum=l==1?INF:-INF; return;}
	int mid=l+r>>1;
	build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);
	t[rt].sum=max(t[rt<<1].sum,t[rt<<1|1].sum);
}

int query(int rt,int lc,int rc,int l,int r)
{
	if(l<=lc&&r>=rc) return t[rt].sum;
	pushdown(rt,lc,rc); int mid=lc+rc>>1,ans=-N*10;
	if(l<=mid) ans=max(ans,query(rt<<1,lc,mid,l,r));
	if(r>mid) ans=max(ans,query(rt<<1|1,mid+1,rc,l,r));
	return ans;
}

int Find(int rt,int lc,int rc,int l,int r,int val)
{
	if(t[rt].sum<val) return 0;
	if(lc==rc) return lc;
	pushdown(rt,lc,rc); int mid=lc+rc>>1;
	if(l<=lc&&r>=rc) return t[rt].sum<val?Find(rt<<1,lc,mid,l,r,val):
							Find(rt<<1|1,mid+1,rc,l,r,val);
	if(r>mid)
	{
		int ans=Find(rt<<1|1,mid+1,rc,l,r,val);
		if(ans) return ans;
	}
	if(l<=mid)
	{
		int ans=Find(rt<<1,lc,mid,l,r,val);
		if(ans) return ans;
	}
	return 0;
}

void change(int rt,int lc,int rc,int l,int r,int val)
{
	if(l<=lc&&r>=rc)
	{
		t[rt].add=max(t[rt].add,val);
		t[rt].sum=max(t[rt].sum,t[rt].add+2*dep[w[rc]]);
		return;
	}
	pushdown(rt,lc,rc); int mid=lc+rc>>1;
	if(l<=mid) change(rt<<1,lc,mid,l,r,val);
	if(r>mid) change(rt<<1|1,mid+1,rc,l,r,val);
	t[rt].sum=max(t[rt<<1].sum,t[rt<<1|1].sum);
}

bool cmp(int &a,int &b)
{
	if(dep[q[a].x]+q[a].t==dep[q[b].x]+q[b].t) return q[a].x<q[b].x;
	return dep[q[a].x]+q[a].t<dep[q[b].x]+q[b].t;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%d",fa+i),G[fa[i]].push_back(i);
	dfs1(0); dfs2(0,0);
	for(int i=1;i<=m;++i)
		ord[i]=i,scanf("%d%d",&q[i].x,&q[i].t);
	sort(ord+1,ord+m+1,cmp); build(1,1,ids);
	for(int i=1;i<=m;++i)
	{
		int now=q[ord[i]].x,tim=q[ord[i]].t;
		int val=dep[now]+tim,tmp=now,ans;
		while(1)
		{
			int res=query(1,1,ids,dfn[top[tmp]],dfn[tmp]);
			if(res>=val) {ans=w[Find(1,1,ids,dfn[top[tmp]],dfn[tmp],val)]; break;}
			tmp=fa[top[tmp]];
		}
		id[ord[i]]=ans; int dta=val-2*dep[ans]-1;
		while(top[now]!=top[ans])
		{
			change(1,1,ids,dfn[top[now]],dfn[now],dta);
			now=fa[top[now]];
		}
		change(1,1,ids,dfn[ans],dfn[now],dta);
	}
	for(int i=1;i<=m;++i)
		printf("%d ",q[i].t+2*(dep[q[i].x]-dep[id[i]]));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5, INF = 0x3f3f3f3f;
struct Tree {int sum, add;} t[N << 2];
struct Que {int x, t;} q[N];
int n, m, siz[N], son[N], top[N], fa[N], dep[N];
int ord[N], dfn[N], ids, w[N], id[N];
vector<int> G[N];

void dfs1(int u)
{
    siz[u] = 1;
    for (int i = 0, v; i < G[u].size(); ++i)
    {
        dep[v = G[u][i]] = dep[u] + 1;
        dfs1(v); siz[u] += siz[v];
        if (!son[u] || siz[v] > siz[son[u]])
            son[u] = v;
    }
}

void dfs2(int u, int tp)
{
    top[u] = tp, dfn[u] = ++ids, w[ids] = u;
    if (son[u]) dfs2(son[u], tp);
    for (int i = 0, v; i < G[u].size(); ++i)
        if ((v = G[u][i]) != son[u])
            dfs2(v, v);
}

inline void pushdown(int rt, int l, int r)
{
    int mid = l + r >> 1;
    t[rt << 1].add = max(t[rt << 1].add, t[rt].add);
    t[rt << 1].sum = max(t[rt << 1].sum, t[rt << 1].add + 2 * dep[w[mid]]);
    t[rt << 1 | 1].add = max(t[rt << 1 | 1].add, t[rt].add);
    t[rt << 1 | 1].sum = max(t[rt << 1 | 1].sum, t[rt << 1 | 1].add + 2 * dep[w[r]]);
}

void build(int rt, int l, int r)
{
    t[rt].add = -INF;
    if (l == r)
    {
        t[rt].sum = l == 1 ? INF : -INF;
        return;
    }
    int mid = l + r >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
    t[rt].sum = max(t[rt << 1].sum, t[rt << 1 | 1].sum);
}

int query(int rt, int lc, int rc, int l, int r)
{
    if (l <= lc && r >= rc) return t[rt].sum;
    pushdown(rt, lc, rc);
    int mid = lc + rc >> 1, ans = -N * 10;
    if (l <= mid)
        ans = max(ans, query(rt << 1, lc, mid, l, r));
    if (r > mid)
        ans = max(ans, query(rt << 1 | 1, mid + 1, rc, l, r));
    return ans;
}

int Find(int rt, int lc, int rc, int l, int r, int val)
{
    if (t[rt].sum < val) return 0;
    if (lc == rc) return lc;
    pushdown(rt, lc, rc);
    int mid = lc + rc >> 1;
    if (l <= lc && r >= rc)
        return t[rt << 1 | 1].sum < val ? Find(rt << 1, lc, mid, l, r, val)
                                        : Find(rt << 1 | 1, mid + 1, rc, l, r, val);
    if (r > mid)
    {
        int ans = Find(rt << 1 | 1, mid + 1, rc, l, r, val);
        if (ans) return ans;
    }
    if (l <= mid)
    {
        int ans = Find(rt << 1, lc, mid, l, r, val);
        if (ans) return ans;
    }
    return 0;
}

void change(int rt, int lc, int rc, int l, int r, int val)
{
    if (l <= lc && r >= rc)
    {
        t[rt].add = max(t[rt].add, val);
        t[rt].sum = max(t[rt].sum, t[rt].add + 2 * dep[w[rc]]);
        return;
    }
    pushdown(rt, lc, rc);
    int mid = lc + rc >> 1;
    if (l <= mid)
        change(rt << 1, lc, mid, l, r, val);
    if (r > mid)
        change(rt << 1 | 1, mid + 1, rc, l, r, val);
    t[rt].sum = max(t[rt << 1].sum, t[rt << 1 | 1].sum);
}

bool cmp(int &a, int &b)
{
    if (dep[q[a].x] + q[a].t == dep[q[b].x] + q[b].t)
        return q[a].x < q[b].x;
    return dep[q[a].x] + q[a].t < dep[q[b].x] + q[b].t;
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i)
        scanf("%d", fa + i), G[fa[i]].push_back(i);
    dfs1(0); dfs2(0, 0);
    for (int i = 1; i <= m; ++i)
        ord[i] = i, scanf("%d%d", &q[i].x, &q[i].t);
    sort(ord + 1, ord + m + 1, cmp);
    build(1, 1, ids);
    for (int i = 1; i <= m; ++i)
    {
        int now = q[ord[i]].x, tim = q[ord[i]].t;
        int val = dep[now] + tim, tmp = now, ans;
        while (1)
        {
            int res = query(1, 1, ids, dfn[top[tmp]], dfn[tmp]);
            if (res >= val)
            {
                ans = w[Find(1, 1, ids, dfn[top[tmp]], dfn[tmp], val)];
                break;
            }
            tmp = fa[top[tmp]];
        }
        id[ord[i]] = ans;
        int dta = val - 2 * dep[ans] - 1;
        while (top[now] != top[ans])
        {
            change(1, 1, ids, dfn[top[now]], dfn[now], dta);
            now = fa[top[now]];
        }
        change(1, 1, ids, dfn[ans], dfn[now], dta);
    }
    for (int i = 1; i <= m; ++i)
        printf("%d ", q[i].t + 2 * (dep[q[i].x] - dep[id[i]]));
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N=2e5+5,INF=0x3f3f3f3f;
struct Tree{int sum,add;}t[N<<2];
struct Que{int x,t;}q[N];
int n,m,siz[N],son[N],top[N],fa[N],dep[N];
int ord[N],dfn[N],ids,w[N],id[N];
vector<int> G[N];

void dfs1(int u)
{
	siz[u]=1;
	for(int i=0,v;i<G[u].size();++i)
	{
		dep[v=G[u][i]]=dep[u]+1;
		dfs1(v); siz[u]+=siz[v];
		if(!son[u]||siz[v]>siz[son[u]]) son[u]=v;
	}
}

void dfs2(int u,int tp)
{
	top[u]=tp,dfn[u]=++ids,w[ids]=u;
	if(son[u]) dfs2(son[u],tp);
	for(int i=0,v;i<G[u].size();++i)
		if((v=G[u][i])!=son[u]) dfs2(v,v);
}

inline void pushdown(int rt,int l,int r)
{
	int mid=l+r>>1;
	t[rt<<1].add=max(t[rt<<1].add,t[rt].add);
	t[rt<<1].sum=max(t[rt<<1].sum,t[rt<<1].add+2*dep[w[mid]]);
	t[rt<<1|1].add=max(t[rt<<1|1].add,t[rt].add);
	t[rt<<1|1].sum=max(t[rt<<1|1].sum,t[rt<<1|1].add+2*dep[w[r]]);
}

void build(int rt,int l,int r)
{
	t[rt].add=-INF;
	if(l==r) {t[rt].sum=l==1?INF:-INF; return;}
	int mid=l+r>>1;
	build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);
	t[rt].sum=max(t[rt<<1].sum,t[rt<<1|1].sum);
}

int query(int rt,int lc,int rc,int l,int r)
{
	if(l<=lc&&r>=rc) return t[rt].sum;
	pushdown(rt,lc,rc); int mid=lc+rc>>1,ans=-N*10;
	if(l<=mid) ans=max(ans,query(rt<<1,lc,mid,l,r));
	if(r>mid) ans=max(ans,query(rt<<1|1,mid+1,rc,l,r));
	return ans;
}

int Find(int rt,int lc,int rc,int l,int r,int val)
{
	if(t[rt].sum<val) return 0;
	if(lc==rc) return lc;
	pushdown(rt,lc,rc); int mid=lc+rc>>1;
	if(l<=lc&&r>=rc) return t[rt].sum<val?Find(rt<<1,lc,mid,l,r,val):
							Find(rt<<1|1,mid+1,rc,l,r,val);
	if(r>mid)
	{
		int ans=Find(rt<<1|1,mid+1,rc,l,r,val);
		if(ans) return ans;
	}
	if(l<=mid)
	{
		int ans=Find(rt<<1,lc,mid,l,r,val);
		if(ans) return ans;
	}
	return 0;
}

void change(int rt,int lc,int rc,int l,int r,int val)
{
	if(l<=lc&&r>=rc)
	{
		t[rt].add=max(t[rt].add,val);
		t[rt].sum=max(t[rt].sum,t[rt].add+2*dep[w[rc]]);
		return;
	}
	pushdown(rt,lc,rc); int mid=lc+rc>>1;
	if(l<=mid) change(rt<<1,lc,mid,l,r,val);
	if(r>mid) change(rt<<1|1,mid+1,rc,l,r,val);
	t[rt].sum=max(t[rt<<1].sum,t[rt<<1|1].sum);
}

bool cmp(int &a,int &b)
{
	if(dep[q[a].x]+q[a].t==dep[q[b].x]+q[b].t) return q[a].x<q[b].x;
	return dep[q[a].x]+q[a].t<dep[q[b].x]+q[b].t;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%d",fa+i),G[fa[i]].push_back(i);
	dfs1(0); dfs2(0,0);
	for(int i=1;i<=m;++i)
		ord[i]=i,scanf("%d%d",&q[i].x,&q[i].t);
	sort(ord+1,ord+m+1,cmp); build(1,1,ids);
	for(int i=1;i<=m;++i)
	{
		int now=q[ord[i]].x,tim=q[ord[i]].t;
		int val=dep[now]+tim,tmp=now,ans;
		while(1)
		{
			int res=query(1,1,ids,dfn[top[tmp]],dfn[tmp]);
			if(res>=val) {ans=w[Find(1,1,ids,dfn[top[tmp]],dfn[tmp],val)]; break;}
			tmp=fa[top[tmp]];
		}
		id[ord[i]]=ans; int dta=val-2*dep[ans]-1;
		while(top[now]!=top[ans])
		{
			change(1,1,ids,dfn[top[now]],dfn[now],dta);
			now=fa[top[now]];
		}
		change(1,1,ids,dfn[ans],dfn[now],dta);
	}
	for(int i=1;i<=m;++i)
		printf("%d ",q[i].t+2*(dep[q[i].x]-dep[id[i]]));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N=2e5+5,INF=0x3f3f3f3f;
struct Tree{int sum,add;}t[N<<2];
struct Que{int x,t;}q[N];
int n,m,siz[N],son[N],top[N],fa[N],dep[N];
int ord[N],dfn[N],ids,w[N],id[N];
vector<int> G[N];

void dfs1(int u)
{
	siz[u]=1;
	for(int i=0,v;i<G[u].size();++i)
	{
		dep[v=G[u][i]]=dep[u]+1;
		dfs1(v); siz[u]+=siz[v];
		if(!son[u]||siz[v]>siz[son[u]]) son[u]=v;
	}
}

void dfs2(int u,int tp)
{
	top[u]=tp,dfn[u]=++ids,w[ids]=u;
	if(son[u]) dfs2(son[u],tp);
	for(int i=0,v;i<G[u].size();++i)
		if((v=G[u][i])!=son[u]) dfs2(v,v);
}

inline void pushdown(int rt,int l,int r)
{
	int mid=l+r>>1;
	t[rt<<1].add=max(t[rt<<1].add,t[rt].add);
	t[rt<<1].sum=max(t[rt<<1].sum,t[rt<<1].add+2*dep[w[mid]]);
	t[rt<<1|1].add=max(t[rt<<1|1].add,t[rt].add);
	t[rt<<1|1].sum=max(t[rt<<1|1].sum,t[rt<<1|1].add+2*dep[w[r]]);
}

void build(int rt,int l,int r)
{
	t[rt].add=-INF;
	if(l==r) {t[rt].sum=l==1?INF:-INF; return;}
	int mid=l+r>>1;
	build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);
	t[rt].sum=max(t[rt<<1].sum,t[rt<<1|1].sum);
}

int query(int rt,int lc,int rc,int l,int r)
{
	if(l<=lc&&r>=rc) return t[rt].sum;
	pushdown(rt,lc,rc); int mid=lc+rc>>1,ans=-N*10;
	if(l<=mid) ans=max(ans,query(rt<<1,lc,mid,l,r));
	if(r>mid) ans=max(ans,query(rt<<1|1,mid+1,rc,l,r));
	return ans;
}

int Find(int rt,int lc,int rc,int l,int r,int val)
{
	if(t[rt].sum<val) return 0;
	if(lc==rc) return lc;
	pushdown(rt,lc,rc); int mid=lc+rc>>1;
	if(l<=lc&&r>=rc) return t[rt<<1|1].sum<val?Find(rt<<1,lc,mid,l,r,val):
							Find(rt<<1|1,mid+1,rc,l,r,val);
	if(r>mid)
	{
		int ans=Find(rt<<1|1,mid+1,rc,l,r,val);
		if(ans) return ans;
	}
	if(l<=mid)
	{
		int ans=Find(rt<<1,lc,mid,l,r,val);
		if(ans) return ans;
	}
	return 0;
}

void change(int rt,int lc,int rc,int l,int r,int val)
{
	if(l<=lc&&r>=rc)
	{
		t[rt].add=max(t[rt].add,val);
		t[rt].sum=max(t[rt].sum,t[rt].add+2*dep[w[rc]]);
		return;
	}
	pushdown(rt,lc,rc); int mid=lc+rc>>1;
	if(l<=mid) change(rt<<1,lc,mid,l,r,val);
	if(r>mid) change(rt<<1|1,mid+1,rc,l,r,val);
	t[rt].sum=max(t[rt<<1].sum,t[rt<<1|1].sum);
}

bool cmp(int &a,int &b)
{
	if(dep[q[a].x]+q[a].t==dep[q[b].x]+q[b].t) return q[a].x<q[b].x;
	return dep[q[a].x]+q[a].t<dep[q[b].x]+q[b].t;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%d",fa+i),G[fa[i]].push_back(i);
	dfs1(0); dfs2(0,0);
	for(int i=1;i<=m;++i)
		ord[i]=i,scanf("%d%d",&q[i].x,&q[i].t);
	sort(ord+1,ord+m+1,cmp); build(1,1,ids);
	for(int i=1;i<=m;++i)
	{
		int now=q[ord[i]].x,tim=q[ord[i]].t;
		int val=dep[now]+tim,tmp=now,ans;
		while(1)
		{
			int res=query(1,1,ids,dfn[top[tmp]],dfn[tmp]);
			if(res>=val) {ans=w[Find(1,1,ids,dfn[top[tmp]],dfn[tmp],val)]; break;}
			tmp=fa[top[tmp]];
		}
		id[ord[i]]=ans; int dta=val-2*dep[ans]-1;
		while(top[now]!=top[ans])
		{
			change(1,1,ids,dfn[top[now]],dfn[now],dta);
			now=fa[top[now]];
		}
		change(1,1,ids,dfn[ans],dfn[now],dta);
	}
	for(int i=1;i<=m;++i)
		printf("%d ",q[i].t+2*(dep[q[i].x]-dep[id[i]]));
	return 0;
}


#include <algorithm>
#include <cstdio>

inline int read(){
	char c=getchar(); int x=0,ft=1;
	for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
	for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
	return x*ft;
}

const int inf=2e9;

const int N=2e5+5;

int n,m,h[N],edge_cnt,a[N],t[N],id[N],ans[N];

struct Edge{ int to,nex; }e[N<<1];

inline void add_edge(int u,int v){
	e[++edge_cnt]=(Edge){v,h[u]}; h[u]=edge_cnt;
}

int d[N],fa[N],sz[N],son[N],top[N],dfn[N],dfc,rk[N];

void dfs1(int u,int pre){
	d[u]=d[pre]+1; fa[u]=pre; sz[u]=1;
	for(int i=h[u];i;i=e[i].nex){
		int v=e[i].to; dfs1(v,u); sz[u]+=sz[v];
		if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;
	}
}

void dfs2(int u,int pre){
	top[u]=pre; dfn[u]=++dfc; rk[dfc]=u;
	if(son[u]) dfs2(son[u],pre);
	for(int i=h[u];i;i=e[i].nex){
		int v=e[i].to; if(v!=son[u]) dfs2(v,v);
	}
}

int mx[N<<2],tag[N<<2],pos;

#define lc (u<<1)
#define rc (u<<1|1)

inline void put_tag(int r,int c,int u){
	mx[u]=2*r+c; tag[u]=c;
}

inline void push_down(int l,int r,int u){
	if(tag[u]!=-inf){
		int mid=(l+r)>>1;
		put_tag(mid,tag[u],lc);
		put_tag(r,tag[u],rc);
		tag[u]=-inf;
	}
}

void modify(int ql,int qr,int c,int l,int r,int u){
	if(ql<=l&&r<=qr) put_tag(r,c,u);
	else{
		int mid=(l+r)>>1; push_down(l,r,u);
		if(ql<=mid) modify(ql,qr,c,l,mid,lc);
		if(qr>mid) modify(ql,qr,c,mid+1,r,rc);
		mx[u]=std::max(mx[lc],mx[rc]);
	}
}

void query(int ql,int qr,int c,int l,int r,int u){
	if(mx[u]<=c) return;
	if(l==r){ pos=rk[l]; return; }
	else{
		int mid=(l+r)>>1; push_down(l,r,u);
		if(pos==-1&&qr>mid) query(ql,qr,c,mid+1,r,rc);
		if(pos==-1&&ql<=mid) query(ql,qr,c,l,mid,lc);
	}
}

int solve(int u,int t){
	int v=u;
	for(;v;v=fa[top[v]]){
		pos=-1; query(dfn[top[v]],dfn[v],t+dfn[v],1,n,1);
		if(pos>0){ t+=d[v]-d[pos]; v=pos; break; }
		t+=d[v]-d[fa[top[v]]];
	}
	if(!v) v=1,--t; int res=t+d[u]-d[v];
	for(;;u=fa[top[u]]){
		if(top[u]==top[v]){
			if(u!=v){
				modify(dfn[v]+1,dfn[u],t+d[u]-d[v]-dfn[u],1,n,1);
			}
			break;
		}
		modify(dfn[top[u]],dfn[u],t+d[u]-d[v]-dfn[u],1,n,1);
	}
	return res;
}

int main(){
	n=read()+1; m=read(); mx[1]=tag[1]=-inf+1;
	for(int i=2;i<=n;++i) add_edge(read()+1,i);
	dfs1(1,0); dfs2(1,1);
	for(int i=1;i<=m;++i) a[i]=read()+1,t[i]=read(),id[i]=i;
	std::sort(id+1,id+1+m,[&](int x,int y){
		if(t[x]+d[a[x]]==t[y]+d[a[y]]) return a[x]<a[y];
		else return t[x]+d[a[x]]<t[y]+d[a[y]];
	});
	for(int i=1;i<=m;++i) ans[id[i]]=solve(a[id[i]],t[id[i]]);
	for(int i=1;i<=m;++i) printf("%d ",ans[i]); return 0;
}


#include <bits/stdc++.h>
#define ls x<<1,l,mid
#define rs x<<1|1,mid+1,r
#define mid ((l+r)>>1)
#define lc x<<1
#define rc x<<1|1
using namespace std;
const int N=200010;
struct Edge{int to,nt;}e[N<<1];
struct Que{int x,t,id;}q[N];
int top[N],dfn[N],fa[N],son[N],sz[N],Index;
int n,m,dep[N],sd[N],cnt,ft[N],Ans[N];
int tag[N<<2],mx[N<<2],dps[N<<2];
int read() {
	int x=0,o=1;char ch=getchar();
	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
	if(ch=='-') o=-1,ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*o;
}
bool cmp(Que x,Que y) {
	if(dep[x.x]+x.t==dep[y.x]+y.t) return x.x<y.x;
	return dep[x.x]+x.t<dep[y.x]+y.t;
}
void Add(int u,int v) {
	e[++cnt]=(Edge){v,ft[u]}; ft[u]=cnt;
	e[++cnt]=(Edge){u,ft[v]}; ft[v]=cnt;
}
void dfs1(int u,int Fa) {
	sz[u]=1,dep[u]=dep[Fa]+1;
	for(int i=ft[u];i;i=e[i].nt) {
		int v=e[i].to;
		if(v==Fa) continue;
		dfs1(v,u),fa[v]=u;
		if(sz[v]>sz[son[u]]) son[u]=v;
		sz[u]+=sz[v];
	}
}
void dfs2(int u,int fa) {
	dfn[u]=++Index,sd[Index]=dep[u];
	if(son[u]) top[son[u]]=top[u],dfs2(son[u],u);
	for(int i=ft[u];i;i=e[i].nt) {
		int v=e[i].to;
		if(v==fa||v==son[u]) continue;
		top[v]=v,dfs2(v,u);
	}
}
void pushup(int x) {
	mx[x]=max(mx[lc],mx[rc]);
}
void put(int x,int y) {
	mx[x]=dps[x]+y,tag[x]=y;
}
void pushdown(int x) {
	if(tag[x]) put(lc,tag[x]),put(rc,tag[x]),tag[x]=0;
}
void Build(int x,int l,int r) {
	if(l==r) {dps[x]=sd[l]<<1;return;}
	Build(ls),Build(rs);
	dps[x]=max(dps[lc],dps[rc]);
}
int Q(int x,int l,int r,int L,int R) {
	if(L<=l&&r<=R) return mx[x];
	pushdown(x);
	int maxx=-2e9;
	if(L<=mid) maxx=max(maxx,Q(ls,L,R));
	if(R>mid) maxx=max(maxx,Q(rs,L,R));
	return maxx;
}
void Update(int x,int l,int r,int L,int R,int val) {
	if(L<=l&&r<=R) {put(x,val);return;}
	pushdown(x);
	if(L<=mid) Update(ls,L,R,val);
	if(R>mid) Update(rs,L,R,val);
	pushup(x);
}
int solve(int x,int t) {
	int p=dfn[x]+1,Ans=0,xx=x;
	for(;x;p=dfn[top[x]],x=fa[top[x]]) {
		int l=dfn[top[x]],r=dfn[x];
		if(Q(1,1,n,l,r)<=t+dep[xx]) continue;
		while(l<=r) {
			int mx=Q(1,1,n,mid,r);
			if(mx>t+dep[xx]) l=mid+1;
			else p=mid,r=mid-1;
		}
		break;
	}
	if(p==dfn[xx]+1) Ans=t;
	else if(p==1) Ans=t+(dep[xx]-1)*2;
	else Ans=t+(dep[xx]-sd[p]+1)*2;
	x=xx;
	//cout<<xx<<' '<<p<<' '<<Ans<<endl;
	for(;x&&dfn[top[x]]>p;x=fa[top[x]])
		Update(1,1,n,dfn[top[x]],dfn[x],Ans-dep[xx]);
	if(p) Update(1,1,n,p,dfn[x],Ans-dep[xx]);
	return Ans;
}

int main() {
	memset(mx,-31,sizeof(mx));
	n=read()+1,m=read();
	for(int i=2;i<=n;i++) Add(i,read()+1);
	for(int i=1;i<=m;i++)
		q[i]=(Que){read()+1,read(),i};
	dfs1(1,0),top[1]=1,dfs2(1,0);
	sd[1]=-1e9,Build(1,1,n),sd[1]=1;
	sort(q+1,q+1+m,cmp);
	//for(int i=1;i<=n;i++) cout<<dfn[i]<<' ';puts("");

	for(int i=1;i<=m;i++)
		Ans[q[i].id]=solve(q[i].x,q[i].t);
	for(int i=1;i<=m;i++)
		printf("%d ",Ans[i]);
	puts("");
	return 0;
}


#include <bits/stdc++.h>
#define ls x<<1,l,mid
#define rs x<<1|1,mid+1,r
#define mid ((l+r)>>1)
#define lc x<<1
#define rc x<<1|1
using namespace std;
const int N=200010;
struct Edge{int to,nt;}e[N<<1];
struct Que{int x,t,id;}q[N];
int top[N],dfn[N],fa[N],son[N],sz[N],Index;
int n,m,dep[N],sd[N],cnt,ft[N],Ans[N];
int tag[N<<2],mx[N<<2],dps[N<<2];
int read() {
	int x=0,o=1;char ch=getchar();
	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
	if(ch=='-') o=-1,ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*o;
}
bool cmp(Que x,Que y) {
	if(dep[x.x]+x.t==dep[y.x]+y.t) return x.x<y.x;
	return dep[x.x]+x.t<dep[y.x]+y.t;
}
void Add(int u,int v) {
	e[++cnt]=(Edge){v,ft[u]}; ft[u]=cnt;
	e[++cnt]=(Edge){u,ft[v]}; ft[v]=cnt;
}
void dfs1(int u,int Fa) {
	sz[u]=1,dep[u]=dep[Fa]+1;
	for(int i=ft[u];i;i=e[i].nt) {
		int v=e[i].to;
		if(v==Fa) continue;
		dfs1(v,u),fa[v]=u;
		if(sz[v]>sz[son[u]]) son[u]=v;
		sz[u]+=sz[v];
	}
}
void dfs2(int u,int fa) {
	dfn[u]=++Index,sd[Index]=dep[u];
	if(son[u]) top[son[u]]=top[u],dfs2(son[u],u);
	for(int i=ft[u];i;i=e[i].nt) {
		int v=e[i].to;
		if(v==fa||v==son[u]) continue;
		top[v]=v,dfs2(v,u);
	}
}
void pushup(int x) {
	mx[x]=max(mx[lc],mx[rc]);
}
void put(int x,int y) {
	mx[x]=dps[x]+y,tag[x]=y;
}
void pushdown(int x) {
	if(tag[x]!=tag[0])
		put(lc,tag[x]),put(rc,tag[x]),tag[x]=tag[0];
}
void Build(int x,int l,int r) {
	if(l==r) {dps[x]=sd[l]<<1;return;}
	Build(ls),Build(rs);
	dps[x]=max(dps[lc],dps[rc]);
}
int Q(int x,int l,int r,int L,int R) {
	if(L<=l&&r<=R) return mx[x];
	pushdown(x);
	int maxx=-2e9;
	if(L<=mid) maxx=max(maxx,Q(ls,L,R));
	if(R>mid) maxx=max(maxx,Q(rs,L,R));
	return maxx;
}
void Update(int x,int l,int r,int L,int R,int val) {
	if(L<=l&&r<=R) {put(x,val);return;}
	pushdown(x);
	if(L<=mid) Update(ls,L,R,val);
	if(R>mid) Update(rs,L,R,val);
	pushup(x);
}
int solve(int x,int t) {
	int p=dfn[x]+1,Ans=0,xx=x;
	for(;x;p=dfn[top[x]],x=fa[top[x]]) {
		int l=dfn[top[x]],r=dfn[x];
		if(Q(1,1,n,l,r)<=t+dep[xx]) continue;
		while(l<=r) {
			int mx=Q(1,1,n,mid,r);
			if(mx>t+dep[xx]) l=mid+1;
			else p=mid,r=mid-1;
		}
		break;
	}
	if(p==dfn[xx]+1) Ans=t;
	else if(p==1) Ans=t+(dep[xx]-1)*2;
	else Ans=t+(dep[xx]-sd[p]+1)*2;
	x=xx;
	//if(xx==2) cout<<xx<<' '<<p<<' '<<Ans<<endl;
	for(;x&&dfn[top[x]]>p;x=fa[top[x]])
		Update(1,1,n,dfn[top[x]],dfn[x],Ans-dep[xx]);
	if(p) Update(1,1,n,p,dfn[x],Ans-dep[xx]);
	return Ans;
}

int main() {
	memset(tag,-31,sizeof(tag));
	memset(mx,-31,sizeof(mx));
	n=read()+1,m=read();
	for(int i=2;i<=n;i++) Add(i,read()+1);
	for(int i=1;i<=m;i++)
		q[i]=(Que){read()+1,read(),i};
	dfs1(1,0),top[1]=1,dfs2(1,0);
	sd[1]=-1e9,Build(1,1,n),sd[1]=1;
	sort(q+1,q+1+m,cmp);
	//for(int i=1;i<=n;i++) cout<<dfn[i]<<' ';puts("");
	for(int i=1;i<=m;i++)
		Ans[q[i].id]=solve(q[i].x,q[i].t);
	for(int i=1;i<=m;i++)
		printf("%d ",Ans[i]);
	puts("");
	return 0;
}