#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
template <typename T>
void dprintln(const T &t) {
  cout << t << endl;
}
template <typename T, typename... Args>
void dprintln(const T &t, const Args &...rest) {
  cout << t << ' ';
  dprintln(rest...);
}
template <typename T>
void println(const T &t) {
  cout << t << '\n';
}
template <typename T, typename... Args>
void println(const T &t, const Args &...rest) {
  cout << t << ' ';
  println(rest...);
}
template <typename T>
void print(const T &t) {
  cout << t << ' ';
}
template <typename T, typename... Args>
void print(const T &t, const Args &...rest) {
  cout << t;
  print(rest...);
}
template <class T>
void scan(T &t) {
  cin >> t;
}
template <class T, class... Args>
void scan(T &a, Args &...rest) {
  cin >> a;
  scan(rest...);
}
using ll = long long;
using vl = vector<ll>;
using vi = vector<int>;
using pii = pair<int, int>;
using vb = vector<bool>;
using vpii = vector<pii>;
template <typename T>
struct bit {
  vector<T> a;
  explicit bit(int n, int v = 0) {
    a.resize(n + 1);
    if (v != 0) {
      for (int i = 1; i <= n; ++i) a[i] = v;
    }
  }
  T sum(T x) {
    T res = 0;
    while (x) {
      res += a[x];
      x -= x & -x;
    }
    return res;
  }
  T sum(int l, int r) {
    if (l > r) return 0;
    return sum(r) - sum(l - 1);
  }
  void add(int x, T v) {
    while (x < a.size()) {
      a[x] += v;
      x += x & -x;
    }
  }
  void clear() { fill(a.begin(), a.end(), 0); }
};
vi get_prime(int n) {
  vi minp(n + 1), p;
  for (int i = 2; i <= n; i++) {
    if (!minp[i]) {
      minp[i] = i;
      p.push_back(i);
    }
    for (auto &x : p) {
      if (x <= minp[i] && x * i <= n)
        minp[x * i] = x;
      else
        break;
    }
  }
  return p;
}
const int mod = 1000000007;
inline void add_mod(ll &x, const ll &y) {
  x += y;
  if (x >= mod) x -= mod;
}
void sub_mod(ll &x, const ll &y) {
  x -= y;
  if (x < 0) x += mod;
}
template <typename T>
using vv = vector<vector<T>>;
template <typename T1, typename T2 = T1>
using vp = vector<pair<T1, T2>>;
template <typename T, int n>
using va = vector<array<T, n>>;
using vec = vector<ll>;
using mat = vector<vec>;
mat get_I(int n) {
  mat res(n, vec(n));
  for (int i = 0; i < n; i++) res[i][i] = 1;
  return res;
}
mat operator*(const mat &a, const mat &b) {
  mat c(a.size(), vec(b[0].size()));
  for (size_t i = 0; i < a.size(); i++) {
    for (size_t j = 0; j < a[0].size(); j++) {
      if (a[i][j]) {
        for (size_t k = 0; k < b[0].size(); k++) {
          add_mod(c[i][k], a[i][j] * b[j][k] % mod);
        }
      }
    }
  }
  return c;
}
vec operator*(const mat &a, const vec &b) {
  vec c(a.size());
  for (size_t i = 0; i < a.size(); i++) {
    for (size_t j = 0; j < a[0].size(); j++) {
      add_mod(c[i], a[i][j] * b[j] % mod);
    }
  }
  return c;
}
mat pow(mat a, ll n) {
  mat res(a.size(), vec(a[0].size()));
  for (size_t i = 0; i < a.size(); i++) {
    res[i][i] = 1;
  }
  while (n) {
    if (n & 1) {
      res = res * a;
    }
    a = a * a;
    n >>= 1;
  }
  return res;
}
struct UF {
  vi par;
  explicit UF(int n) {
    par.assign(n + 1, 0);
    for (int i = (1); i < (n + 1); ++i) par[i] = i;
  }
  int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); }
  void unite(int x, int y) { par[find(x)] = find(y); }
};
vi get_popcnt(int n) {
  vi res(n + 1);
  for (int i = (0); i < (n); ++i) {
    if (i * 2 <= n) res[i * 2] = res[i];
    if ((i & 1) == 0) res[i + 1] = res[i] + 1;
  }
  return res;
}
template <class T>
struct SparseTable {
  std::vector<std::vector<T>> f;
  std::vector<int> lg;
  SparseTable() {}
  SparseTable(const std::vector<T> &a) { init(a); }
  void init(const std::vector<T> &a) {
    int n = a.size();
    lg.assign(n + 1, 0);
    for (int i = 1, j = 0; i <= n; i++) {
      if (i == (1 << (j + 1))) j++;
      lg[i] = j;
    }
    f.assign(lg.back() + 1, std::vector<T>(a.size()));
    f[0] = a;
    for (int j = 1; (1 << j) <= n; j++) {
      for (int i = 0; i + (1 << j) - 1 < n; i++) {
        f[j][i] = min(f[j - 1][i], f[j - 1][i + (1 << (j - 1))]);
      }
    }
  }
  T query(int l, int r) {
    int j = lg[r - l + 1];
    return min(f[j][l], f[j][r - (1 << j) + 1]);
  }
};
struct LCA {
  const std::vector<std::vector<int>> &g;
  SparseTable<std::pair<int, int>> st;
  std::vector<int> sp;
  std::vector<int> dep, ST, ED;
  LCA(const std::vector<std::vector<int>> &graph, int root = 1) : g(graph) {
    int sz = graph.size();
    dep = ST = ED = std::vector<int>(sz);
    dfs(root, -1, 0);
    std::vector<std::pair<int, int>> vec;
    for (int i = 0; i < sp.size(); i++) {
      vec.emplace_back(ST[sp[i]], sp[i]);
    }
    st.init(vec);
  }
  void dfs(int u, int fa, int d) {
    dep[u] = d + 1;
    ST[u] = sp.size();
    sp.push_back(u);
    for (auto v : g[u]) {
      if (v != fa) {
        dfs(v, u, d + 1);
        sp.push_back(u);
      }
    }
    ED[u] = (int)sp.size() - 1;
  }
  int query(int u, int v) {
    int l = ST[u], r = ST[v];
    if (l > r) std::swap(l, r);
    return st.query(l, r).second;
  }
  bool on_path(int x, int y, int z) {
    int anc = query(x, y);
    if (dep[z] < dep[anc]) return false;
    return query(x, z) == z || query(y, z) == z;
  }
};
const int N = (int)2e5 + 5, M = 1005;
struct node {
  bool ok;
  int u, v;
} tree[N * 4];
int leaf[N];
int p[N];
int v[N];
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  vv<int> g(n + 1);
  for (int i = (1); i < (n + 1); ++i) cin >> p[i], v[p[i]] = i;
  for (int i = (2); i < (n + 1); ++i) {
    int x;
    cin >> x;
    g[x].push_back(i);
  }
  LCA lca(g);
  auto check = [&lca](int a, int b, int c, int d) -> vi {
    if (a == 0) return {c, d};
    int x[4] = {a, b, c, d};
    for (int i = (0); i < (3); ++i)
      for (int j = (i + 1); j < (4); ++j) {
        int anc = lca.query(x[i], x[j]);
        bool flag = true;
        for (int k = (0); k < (4); ++k) {
          if (k != i && k != j) {
            int t = x[k];
            if (!lca.on_path(x[i], x[j], t)) {
              flag = false;
              break;
            }
          }
        }
        if (flag) return {x[i], x[j]};
      }
    return {-1, -1};
  };
  auto push_up = [&check](int id) {
    auto &f = tree[id], lson = tree[id * 2], rson = tree[id * 2 + 1];
    if (lson.ok && rson.ok) {
      auto res = check(lson.u, lson.v, rson.u, rson.v);
      if (res[0] != -1) {
        f.ok = true;
        f.u = res[0];
        f.v = res[1];
      } else
        f.ok = false;
    } else {
      f.ok = false;
    }
  };
  function<void(int, int, int)> build;
  build = [&build, &push_up](int id, int l, int r) {
    if (l == r) {
      leaf[l] = id;
      tree[id].u = tree[id].v = v[l];
      tree[id].ok = true;
      return;
    }
    int mid = (l + r) / 2;
    build(id * 2, l, mid);
    build(id * 2 + 1, mid + 1, r);
    push_up(id);
  };
  build(1, 0, n - 1);
  auto work = [&push_up](int i) {
    int id = leaf[p[i]];
    tree[id].u = tree[id].v = i;
    while (id != 1) {
      id /= 2;
      push_up(id);
    }
  };
  auto upd = [&work](int i, int j) {
    swap(p[i], p[j]);
    work(i);
    work(j);
  };
  function<int(int, int, int, int, int)> query;
  query = [&check, &query](int id, int l, int r, int u, int v) {
    if (tree[id].ok) {
      auto t = check(u, v, tree[id].u, tree[id].v);
      if (t[0] != -1) return r - l + 1;
      if (l == r) return 0;
    }
    int mid = (l + r) / 2;
    auto &lson = tree[id * 2];
    if (lson.ok) {
      auto t = check(u, v, lson.u, lson.v);
      if (t[0] != -1) {
        return mid - l + 1 + query(id * 2 + 1, mid + 1, r, t[0], t[1]);
      }
    }
    return query(id * 2, l, mid, u, v);
  };
  int q;
  cin >> q;
  for (int _ = 0, __ = (int)q; _ < __; _++) {
    int t, i, j;
    scan(t);
    if (t == 1) {
      scan(i, j);
      upd(i, j);
    } else {
      println(query(1, 0, n - 1, 0, 0));
    }
  }
  return 0;
}
