#include <bits/stdc++.h>
using namespace std;
const int M = 3e5 + 10;
int n;
int pos[M], val[M];
struct ss {
  int to, last;
  ss() {}
  ss(int a, int b) : to(a), last(b) {}
} g[M << 1];
int head[M], cnt;
void add(int a, int b) {
  g[++cnt] = ss(b, head[a]);
  head[a] = cnt;
  g[++cnt] = ss(a, head[b]);
  head[b] = cnt;
}
int dep[M], sze[M], son[M], top[M], dfn[M], f[M], tim;
void dfs1(int a) {
  sze[a] = 1;
  for (int i = head[a]; i; i = g[i].last) {
    if (g[i].to == f[a]) continue;
    f[g[i].to] = a;
    dep[g[i].to] = dep[a] + 1;
    dfs1(g[i].to);
    sze[a] += sze[g[i].to];
    if (!son[a] || sze[son[a]] < sze[g[i].to]) son[a] = g[i].to;
  }
}
void dfs2(int a, int b) {
  top[a] = b;
  dfn[a] = ++tim;
  if (!son[a]) return;
  dfs2(son[a], b);
  for (int i = head[a]; i; i = g[i].last) {
    if (g[i].to == f[a] || g[i].to == son[a]) continue;
    dfs2(g[i].to, g[i].to);
  }
}
int Lca(int a, int b) {
  while (top[a] != top[b]) {
    if (dep[top[a]] < dep[top[b]]) swap(a, b);
    a = f[top[a]];
  }
  if (dep[a] < dep[b])
    return a;
  else
    return b;
}
bool isin(int a, int b) {
  return dfn[a] <= dfn[b] && dfn[b] <= dfn[a] + sze[a] - 1;
}
int ls[4];
struct node {
  int x, y;
  node() {}
  node(int a, int b) : x(a), y(b) {}
  bool notcon() { return x == -1 || y == -1; }
  friend node operator+(node &a, node &b) {
    if (a.notcon() || b.notcon()) return node(-1, -1);
    ls[0] = a.x;
    ls[1] = a.y;
    ls[2] = b.x;
    ls[3] = b.y;
    for (int i = 0; i <= 3; i++) {
      for (int j = 0; j <= 3; j++) {
        if (ls[i] == ls[j]) continue;
        int lca = Lca(ls[i], ls[j]), flag = 1;
        for (int k = 0; k <= 3; k++) {
          if (k != i && k != j) {
            if (!isin(lca, ls[k]) ||
                (isin(lca, ls[k]) &&
                 !(isin(ls[k], ls[i]) || isin(ls[k], ls[j])))) {
              flag = 0;
              break;
            }
          }
        }
        if (flag) return node(ls[i], ls[j]);
      }
    }
    return node(-1, -1);
  }
};
node s[M << 2];
void pushup(int o) { s[o] = s[o << 1] + s[o << 1 | 1]; }
void build(int o, int l, int r) {
  if (l == r) {
    s[o] = node(pos[l], pos[l]);
    return;
  }
  int mid = l + r >> 1;
  build(o << 1, l, mid);
  build(o << 1 | 1, mid + 1, r);
  pushup(o);
}
void update(int o, int l, int r, int v) {
  if (l == r) {
    s[o] = node(pos[l], pos[l]);
    return;
  }
  int mid = l + r >> 1;
  if (v <= mid)
    update(o << 1, l, mid, v);
  else
    update(o << 1 | 1, mid + 1, r, v);
  pushup(o);
}
int query(int o, int l, int r, node a) {
  if (l == r) return l;
  int mid = l + r >> 1;
  node now = a + s[o << 1];
  if (now.x != -1)
    return query(o << 1 | 1, mid + 1, r, now);
  else
    return query(o << 1, l, mid, a);
}
int Q, opt, a, b;
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &val[i]);
    pos[++val[i]] = i;
  }
  pos[n + 1] = -1;
  for (int i = 2; i <= n; i++) {
    scanf("%d", &a);
    add(a, i);
  }
  dfs1(1);
  dfs2(1, 1);
  build(1, 1, n + 1);
  for (scanf("%d", &Q); Q--;) {
    scanf("%d", &opt);
    if (opt == 1) {
      scanf("%d%d", &a, &b);
      swap(pos[val[a]], pos[val[b]]);
      swap(val[a], val[b]);
      update(1, 1, n + 1, val[a]);
      update(1, 1, n + 1, val[b]);
    } else {
      printf("%d\n", query(1, 1, n + 1, node(pos[1], pos[1])) - 1);
    }
  }
  return 0;
}
