#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;   }