#include <bits/stdc++.h>
const int N = 2e5;
int n, m, len, a[N + 5], b[N + 5], eul[N + N + 5], dep[N + 5], pos[N + 5];
std::vector<int> e[N + 5];
template <int N>
struct RMQ {
  static const int LogN = 18;
  int lg[N + 5], f[LogN + 1][N + 5];
  int myMin(const int &x, const int &y) { return dep[x] < dep[y] ? x : y; }
  void build(int *a, int n) {
    for (int i = 2; i <= n; i++) lg[i] = lg[i >> 1] + 1;
    std::copy(a + 1, a + n + 1, f[0] + 1);
    for (int i = 1; i <= lg[n]; i++) {
      for (int j = 1; j + (1 << i) - 1 <= n; j++) {
        f[i][j] = myMin(f[i - 1][j], f[i - 1][j + (1 << (i - 1))]);
      }
    }
  }
  int query(int l, int r) {
    l = pos[l], r = pos[r];
    if (l > r) std::swap(l, r);
    int k = lg[r - l + 1];
    return myMin(f[k][l], f[k][r - (1 << k) + 1]);
  }
  int dist(int u, int v) { return dep[u] + dep[v] - (dep[query(u, v)] << 1); }
};
RMQ<N + N> R;
struct Node {
  int u, v;
  Node(int u = -1, int v = -1) : u(u), v(v) {}
  Node merge(int w) {
    if (u == -1 || w == -1) return Node();
    int d1 = R.dist(u, v), d2 = R.dist(u, w), d3 = R.dist(v, w);
    return d2 + d3 == d1   ? Node(u, v)
           : d1 + d3 == d2 ? Node(u, w)
           : d1 + d2 == d3 ? Node(v, w)
                           : Node();
  }
  friend Node operator+(Node x, Node y) { return x.merge(y.u).merge(y.v); }
};
template <int MAX>
struct SegmentTree {
  static const int N = MAX << 2;
  Node seg[N + 5];
  void build(int u, int l, int r) {
    if (l == r) return seg[u] = Node(b[l], b[l]), void();
    int mid = (l + r) >> 1;
    build((u << 1), l, mid), build((u << 1 | 1), mid + 1, r);
    seg[u] = seg[(u << 1)] + seg[(u << 1 | 1)];
  }
  void modify(int x, int u, int l, int r) {
    if (l == r) return seg[u] = Node(b[l], b[l]), void();
    int mid = (l + r) >> 1;
    x <= mid ? modify(x, (u << 1), l, mid)
             : modify(x, (u << 1 | 1), mid + 1, r);
    seg[u] = seg[(u << 1)] + seg[(u << 1 | 1)];
  }
  int query(Node &cur, int u, int l, int r) {
    if (seg[u].u != -1) {
      if (cur.u == -1) return cur = seg[u], r + 1;
      Node tmp = cur + seg[u];
      if (tmp.u != -1) return cur = tmp, r + 1;
    }
    if (l == r) return l;
    int mid = (l + r) >> 1;
    int mex = query(cur, (u << 1), l, mid);
    return mex <= mid ? mex : query(cur, (u << 1 | 1), mid + 1, r);
  }
  void print(int u, int l, int r) {
    if (l == r)
      return printf("val [%d, %d] on node (%d, %d)\n", l, r, seg[u].u,
                    seg[u].v),
             void();
    int mid = (l + r) >> 1;
    print((u << 1), l, mid), print((u << 1 | 1), mid + 1, r);
    printf("val [%d, %d] on node (%d, %d)\n", l, r, seg[u].u, seg[u].v);
  }
};
SegmentTree<N> T;
void dfs(int u, int p) {
  dep[eul[pos[u] = ++len] = u] = dep[p] + 1;
  for (const auto &v : e[u]) dfs(v, u), eul[++len] = u;
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]), b[a[i]] = i;
  }
  for (int p, i = 2; i <= n; i++) scanf("%d", &p), e[p].push_back(i);
  dfs(1, 0);
  R.build(eul, len);
  T.build(1, 0, n - 1);
  scanf("%d", &m);
  for (int opt, i = 1; i <= m; i++) {
    scanf("%d", &opt);
    if (opt == 1) {
      int u, v;
      scanf("%d%d", &u, &v);
      std::swap(b[a[u]], b[a[v]]), std::swap(a[u], a[v]);
      T.modify(a[u], 1, 0, n - 1);
      T.modify(a[v], 1, 0, n - 1);
    } else {
      Node tmp = Node();
      printf("%d\n", T.query(tmp, 1, 0, n - 1));
    }
  }
  return 0;
}
