#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
struct Node {
  int lson, rson, size;
} tree[MAXN * 20];
vector<int> ver[MAXN];
int rot[MAXN], siz[MAXN], son[MAXN], w[MAXN], f[MAXN][25];
int nnum[MAXN], ttop[MAXN], onum[MAXN], dep[MAXN], vis[MAXN];
int n, m, RT = 0, tot, cnt, ts;
inline int read() {
  int tot = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    tot = (tot << 1) + (tot << 3) + (c ^ 48);
    c = getchar();
  }
  return tot * f;
}
inline void dfs(int u, int fa) {
  siz[u] = 1;
  f[u][0] = fa;
  dep[u] = dep[fa] + 1;
  int maxh = 0;
  for (int i = 1; i <= 20; i++) f[u][i] = f[f[u][i - 1]][i - 1];
  for (int i = 0; i < ver[u].size(); i++) {
    int v = ver[u][i];
    if (v == fa) continue;
    dfs(v, u);
    siz[u] += siz[v];
    if (siz[v] > maxh) maxh = siz[v], son[u] = v;
  }
}
inline void redfs(int u, int fa, int topu) {
  ttop[u] = topu;
  nnum[u] = ++ts;
  onum[ts] = u;
  if (son[u]) redfs(son[u], u, topu);
  for (int i = 0; i < ver[u].size(); i++) {
    int v = ver[u][i];
    if (v == fa || v == son[u]) continue;
    redfs(v, u, v);
  }
}
inline void pushup(int o) {
  tree[o].size = tree[tree[o].lson].size + tree[tree[o].rson].size;
}
inline void build(int &o, int l, int r) {
  o = ++tot;
  if (l == r) {
    tree[o].size = 0;
    return;
  }
  int mid = (l + r) >> 1;
  build(tree[o].lson, l, mid);
  build(tree[o].rson, mid + 1, r);
  pushup(o);
}
inline void update(int &o, int lo, int l, int r, int pos) {
  o = ++tot;
  if (l == r) {
    tree[o].size = 1;
    return;
  }
  int mid = (l + r) >> 1;
  if (pos <= mid)
    tree[o].rson = tree[lo].rson,
    update(tree[o].lson, tree[lo].lson, l, mid, pos);
  else
    tree[o].lson = tree[lo].lson,
    update(tree[o].rson, tree[lo].rson, mid + 1, r, pos);
  pushup(o);
}
inline int query(int o1, int o2, int l, int r, int ql, int qr) {
  if (l >= ql && r <= qr) return tree[o2].size - tree[o1].size;
  int mid = (l + r) >> 1;
  int ans = 0;
  if (ql <= mid) ans += query(tree[o1].lson, tree[o2].lson, l, mid, ql, qr);
  if (qr > mid) ans += query(tree[o1].rson, tree[o2].rson, mid + 1, r, ql, qr);
  return ans;
}
inline int LCA(int x, int y) {
  while (ttop[x] != ttop[y]) {
    if (dep[ttop[x]] < dep[ttop[y]]) swap(x, y);
    x = f[ttop[x]][0];
  }
  return dep[x] < dep[y] ? x : y;
}
inline int jump(int x, int ed) {
  for (int i = 20; i >= 0; i--)
    if (dep[f[x][i]] > dep[ed]) x = f[x][i];
  return x;
}
inline int upsolve(int fr, int to, int qy, int k) {
  int l = nnum[to], r = nnum[fr], ans = to;
  while (l <= r) {
    int mid = (l + r) >> 1;
    int num = dep[fr] - dep[onum[mid]] + 1;
    int delt = query(rot[qy], rot[cnt], 1, n, mid, nnum[fr]);
    if (num - delt >= k)
      ans = onum[mid], l = mid + 1;
    else
      r = mid - 1;
  }
  return ans;
}
inline int downsolve(int fr, int to, int qy, int k) {
  int l = nnum[to], r = nnum[fr], ans = to;
  while (l <= r) {
    int mid = (l + r) >> 1;
    int num = dep[onum[mid]] - dep[to] + 1;
    int delt = query(rot[qy], rot[cnt], 1, n, nnum[to], mid);
    if (num - delt >= k)
      ans = onum[mid], r = mid - 1;
    else
      l = mid + 1;
  }
  return ans;
}
inline int goup(int st, int ed, int qy, int &k) {
  while (ttop[st] != ttop[ed]) {
    int num = dep[st] - dep[ttop[st]] + 1;
    int delt = query(rot[qy], rot[cnt], 1, n, nnum[ttop[st]], nnum[st]);
    if (num - delt >= k) {
      return upsolve(st, ttop[st], qy, k);
    } else
      k -= num - delt, st = f[ttop[st]][0];
  }
  int num = dep[st] - dep[ed] + 1;
  int delt = query(rot[qy], rot[cnt], 1, n, nnum[ed], nnum[st]);
  if (num - delt >= k)
    return upsolve(st, ed, qy, k);
  else {
    k -= num - delt;
    return 0;
  }
}
inline int godown(int st, int ed, int qy, int k) {
  if (st == ed) {
    if (k == 1 && vis[st] <= qy)
      return st;
    else
      return 0;
  }
  stack<int> sta;
  while (ttop[st] != ttop[ed])
    sta.push(st), sta.push(ttop[st]), st = f[ttop[st]][0];
  if (st != ed)
    sta.push(st);
  else {
    if (vis[ed] <= qy) {
      if (k == 1)
        return ed;
      else
        k--;
    }
    ed = sta.top();
    sta.pop();
  }
  while (sta.size()) {
    int u = sta.top();
    sta.pop();
    int num = dep[u] - dep[ed] + 1;
    int delt = query(rot[qy], rot[cnt], 1, n, nnum[ed], nnum[u]);
    if (num - delt >= k)
      return downsolve(u, ed, qy, k);
    else {
      k -= num - delt;
      if (sta.size()) {
        ed = sta.top();
        sta.pop();
      }
    }
  }
  return 0;
}
signed main() {
  n = read();
  for (int i = 1; i <= n; i++) {
    f[i][0] = read();
    if (f[i][0])
      ver[f[i][0]].push_back(i);
    else
      RT = i;
  }
  dfs(RT, RT);
  redfs(RT, RT, RT);
  build(rot[0], 1, n);
  m = read();
  for (int i = 1; i <= m; i++) {
    int typ = read();
    if (typ == 1) {
      int p = read();
      w[i] = ++cnt;
      update(rot[cnt], rot[cnt - 1], 1, n, nnum[p]);
      vis[p] = cnt;
    } else {
      w[i] = w[i - 1];
      int st = read(), ed = read(), k = read(), y = read();
      if (f[st][0] == ed || f[ed][0] == st) {
        printf("-1\n");
        continue;
      }
      y = w[y];
      int fa = LCA(st, ed);
      if (fa == st) {
        st = jump(ed, fa);
        ed = f[ed][0];
        int t = godown(ed, st, y, k);
        if (!t)
          printf("-1\n");
        else
          printf("%d\n", t);
      } else if (fa == ed) {
        ed = jump(st, fa), st = f[st][0];
        int t = goup(st, ed, y, k);
        if (!t)
          printf("-1\n");
        else
          printf("%d\n", t);
      } else {
        st = f[st][0];
        ed = f[ed][0];
        int t = goup(st, fa, y, k);
        if (t)
          printf("%d\n", t);
        else if (ed == fa) {
          printf("-1\n");
          continue;
        } else {
          fa = jump(ed, fa);
          t = godown(ed, fa, y, k);
          if (t)
            printf("%d\n", t);
          else
            printf("-1\n");
        }
      }
    }
  }
  return 0;
}
