#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
const int N = 5e5 + 10;
const long long INF = 1e18;
const int inf = 1e9 + 1;
const double eps = 1e-9;
const int SQ = 300;
pair<long long, long long> tree[N];
set<int> all;
int f[N];
multiset<long long> S[N];
int n, q;
long long t[N];
long long ch[N];
set<int> gr[N];
void build(int v, int l, int r) {
  if (l == r) {
    tree[v] = make_pair(INF, -INF);
    return;
  }
  int m = (l + r) >> 1;
  build(v + v, l, m);
  build(v + v + 1, m + 1, r);
  tree[v].first = min(tree[v + v].first, tree[v + v + 1].first);
  tree[v].second = max(tree[v + v].second, tree[v + v + 1].second);
}
void update(int v, int l, int r, int pos, long long val, long long d = -1) {
  if (l == r) {
    if (d != -1) {
      d = -INF;
    } else {
      d = val;
    }
    tree[v] = make_pair(val, d);
    return;
  }
  int m = (l + r) >> 1;
  if (m >= pos) {
    update(v + v, l, m, pos, val, d);
  } else {
    update(v + v + 1, m + 1, r, pos, val, d);
  }
  tree[v].first = min(tree[v + v].first, tree[v + v + 1].first);
  tree[v].second = max(tree[v + v].second, tree[v + v + 1].second);
}
long long calc(int v) {
  long long val = t[v] / ((int)gr[v].size() + 2);
  return val;
}
long long own(int v, int len) {
  long long ret = t[v] - (t[v] / len) * (len - 1);
  return ret;
}
void upd(int v, long long old = -1) {
  if ((int)gr[f[v]].size() < SQ) {
    update(1, 0, n - 1, v, ch[v] + calc(f[v]));
  } else {
    int t = f[v];
    update(1, 0, n - 1, v, INF, 1);
    S[t].erase(S[t].find(old));
    S[t].insert(ch[v]);
  }
}
void recalc(int v, int val, long long old) {
  ch[v] -= own(v, (int)gr[v].size() + 2 - val);
  ch[v] += own(v, (int)gr[v].size() + 2);
  upd(v, old);
}
void remEdge(int a, int b) {
  long long oldb = ch[b];
  ch[b] -= calc(a);
  if ((int)gr[b].size() == SQ) {
    int v = f[b];
    long long old = ch[v];
    ch[v] -= calc(b);
    gr[b].erase(a);
    ch[v] += calc(b);
    upd(v, old);
    S[b].clear();
    for (auto e : gr[b]) {
      update(1, 0, n - 1, e, ch[e] + calc(b));
    }
    all.erase(b);
    recalc(b, -1, oldb);
    return;
  }
  if ((int)gr[b].size() < SQ) {
    int v = f[b];
    long long old = ch[v];
    ch[v] -= calc(b);
    gr[b].erase(a);
    ch[v] += calc(b);
    upd(v, old);
    for (auto e : gr[b]) {
      update(1, 0, n - 1, e, ch[e] + calc(b));
    }
    update(1, 0, n - 1, a, INF, 1);
    recalc(b, -1, oldb);
    return;
  }
  int v = f[b];
  long long old = ch[v];
  ch[v] -= calc(b);
  gr[b].erase(a);
  ch[v] += calc(b);
  S[b].erase(S[b].find(ch[a]));
  upd(v, old);
  recalc(b, -1, oldb);
}
void addEdge(int a, int b) {
  long long oldb = ch[b];
  ch[b] += calc(a);
  if ((int)gr[b].size() + 1 == SQ) {
    int v = f[b];
    long long old = ch[v];
    ch[v] -= calc(b);
    gr[b].insert(a);
    ch[v] += calc(b);
    upd(v, old);
    for (auto e : gr[b]) {
      update(1, 0, n - 1, e, INF, 1);
      S[b].insert(ch[e]);
    }
    recalc(b, 1, oldb);
    all.insert(b);
    return;
  }
  if ((int)gr[b].size() >= SQ) {
    int v = f[b];
    long long old = ch[v];
    ch[v] -= calc(b);
    gr[b].insert(a);
    ch[v] += calc(b);
    upd(v, old);
    update(1, 0, n - 1, a, INF, 1);
    S[b].insert(ch[a]);
    recalc(b, 1, oldb);
    return;
  }
  int v = f[b];
  long long old = ch[v];
  ch[v] -= calc(b);
  gr[b].insert(a);
  ch[v] += calc(b);
  upd(v, old);
  for (auto e : gr[b]) {
    update(1, 0, n - 1, e, ch[e] + calc(b));
  }
  recalc(b, 1, oldb);
}
int main() {
  ios ::sync_with_stdio(false);
  cin >> n >> q;
  for (int(i) = (0); (i) < (n); ++(i)) cin >> t[i];
  for (int(i) = (0); (i) < (n); ++(i)) {
    cin >> f[i];
    f[i]--;
    gr[f[i]].insert(i);
  }
  build(1, 0, n - 1);
  for (int(i) = (0); (i) < (n); ++(i)) {
    ch[i] = 0;
    for (auto e : gr[i]) {
      ch[i] += calc(e);
    }
    int len = (int)gr[i].size() + 2;
    ch[i] += t[i] - (t[i] / len) * (len - 1);
    if ((int)gr[i].size() >= SQ) {
      all.insert(i);
    }
    int v = f[i];
    if ((int)gr[v].size() >= SQ) {
      S[v].insert(ch[i]);
    } else {
      update(1, 0, n - 1, i, ch[i] + calc(v));
    }
  }
  for (int(i) = (0); (i) < (q); ++(i)) {
    int t;
    cin >> t;
    if (t == 1) {
      int a, b;
      cin >> a >> b;
      a--;
      b--;
      remEdge(a, f[a]);
      addEdge(a, b);
      f[a] = b;
    } else if (t == 2) {
      int a;
      cin >> a;
      a--;
      long long res = ch[a];
      int v = f[a];
      res += calc(v);
      cout << res << endl;
    } else {
      pair<long long, long long> res = tree[1];
      for (auto e : all) {
        long long minVal = *S[e].begin() + calc(e);
        res.first = min(res.first, minVal);
        auto it = S[e].end();
        it--;
        long long maxVal = *it + calc(e);
        res.second = max(res.second, maxVal);
      }
      cout << res.first << " " << res.second << endl;
    }
  }
  return 0;
}
