#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
const long long INF = 1e18;
long long t[MAXN];
int f[MAXN];
int n, q;
struct Query {
  int t, i, j;
  bool read() {
    if (scanf("%d", &t) < 1) {
      return false;
    }
    if (t == 1) {
      scanf("%d%d", &i, &j);
      --i;
      --j;
    } else if (t == 2) {
      scanf("%d", &i);
      --i;
    } else {
      assert(t == 3);
    }
    return true;
  }
};
Query qs[MAXN];
bool read() {
  if (scanf("%d%d", &n, &q) < 2) {
    return false;
  }
  for (int i = 0; i < (int)n; ++i) {
    scanf("%lld", &t[i]);
  }
  for (int i = 0; i < (int)n; ++i) {
    scanf("%d", &f[i]);
    --f[i];
  }
  for (int i = 0; i < (int)q; ++i) {
    assert(qs[i].read());
  }
  return true;
}
bool mark0[MAXN];
bool mark1[MAXN];
vector<int> marked0;
vector<int> marked1;
long long ans[MAXN];
int deg[MAXN];
bool is_cand[MAXN];
vector<int> cands;
long long me(int v) { return t[v] - (deg[v] + 1) * (t[v] / (deg[v] + 2)); }
bool outside[MAXN];
vector<int> who_link[MAXN];
long long cur_ans[MAXN];
void go(int l, int r) {
  for (int i = 0; i < (int)n; ++i) {
    mark0[i] = false;
  }
  marked0.clear();
  for (int i = l; i < r; ++i) {
    if (qs[i].t == 1) {
      int v = qs[i].i;
      int to = qs[i].j;
      int old_to = f[v];
      marked0.push_back(v);
      marked0.push_back(to);
      marked0.push_back(old_to);
    }
  }
  sort(begin(marked0), end(marked0));
  marked0.resize(unique(begin(marked0), end(marked0)) - marked0.begin());
  for (int x : marked0) {
    mark0[x] = true;
  }
  for (int i = 0; i < (int)n; ++i) {
    deg[i] = 0;
  }
  for (int i = 0; i < (int)n; ++i) {
    ++deg[f[i]];
  }
  for (int i = 0; i < (int)n; ++i) {
    ans[i] = me(i);
  }
  for (int i = 0; i < (int)n; ++i) {
    ans[i] += t[f[i]] / (deg[f[i]] + 2);
    ans[f[i]] += t[i] / (deg[i] + 2);
  }
  for (int i = 0; i < (int)n; ++i) {
    outside[i] = true;
  }
  for (int i = 0; i < (int)n; ++i) {
    if (mark0[i]) {
      outside[i] = false;
      outside[f[i]] = false;
    }
    if (mark0[f[i]]) {
      outside[i] = false;
    }
  }
  long long max_outside = -1;
  long long min_outside = INF;
  for (int i = 0; i < (int)n; ++i) {
    if (outside[i]) {
      max_outside = max(max_outside, ans[i]);
      min_outside = min(min_outside, ans[i]);
    }
  }
  for (int i = 0; i < (int)n; ++i) {
    mark1[i] = false;
  }
  marked1.clear();
  for (int i = 0; i < (int)n; ++i) {
    if (mark0[i] && !mark0[f[i]]) {
      marked1.push_back(f[i]);
    }
  }
  sort(begin(marked1), end(marked1));
  marked1.resize(unique(begin(marked1), end(marked1)) - marked1.begin());
  for (int x : marked1) {
    mark1[x] = true;
  }
  for (int x : marked0) {
    who_link[x].clear();
  }
  for (int i = 0; i < (int)n; ++i) {
    if (mark0[i] || mark1[i]) {
      continue;
    }
    if (!mark0[f[i]]) {
      continue;
    }
    who_link[f[i]].push_back(i);
  }
  cands.clear();
  for (int x : marked0) {
    if (who_link[x].empty()) {
      continue;
    }
    int mn = -1;
    long long mn_val = INF;
    int mx = -1;
    long long mx_val = -1;
    for (int i = 0; i < (int)((int)(who_link[x]).size()); ++i) {
      int v = who_link[x][i];
      long long cur_val = ans[v] - (t[x] / (deg[x] + 2));
      if (cur_val > mx_val) {
        mx_val = cur_val;
        mx = v;
      }
      if (cur_val < mn_val) {
        mn_val = cur_val;
        mn = v;
      }
    }
    assert(mx != -1);
    cands.push_back(mx);
    assert(mn != -1);
    cands.push_back(mn);
  }
  sort(begin(cands), end(cands));
  cands.resize(unique(begin(cands), end(cands)) - cands.begin());
  for (int i = 0; i < (int)n; ++i) {
    is_cand[i] = false;
  }
  for (int x : cands) {
    is_cand[x] = true;
  }
  for (int i = 0; i < (int)n; ++i) {
    if (mark0[f[i]]) {
      ans[i] -= t[f[i]] / (deg[f[i]] + 2);
    }
    if (mark0[i]) {
      ans[f[i]] -= t[i] / (deg[i] + 2);
    }
    ans[i] -= me(i);
  }
  vector<int> all_marked;
  for (int x : marked0) {
    all_marked.push_back(x);
  }
  for (int x : marked1) {
    all_marked.push_back(x);
  }
  for (int x : cands) {
    all_marked.push_back(x);
  }
  sort(begin(all_marked), end(all_marked));
  all_marked.resize(unique(begin(all_marked), end(all_marked)) -
                    all_marked.begin());
  for (int i = l; i < r; ++i) {
    if (qs[i].t == 1) {
      int v = qs[i].i;
      int to = qs[i].j;
      assert(v != to);
      assert(f[v] != to);
      assert(mark0[v]);
      assert(mark0[f[v]]);
      assert(mark0[to]);
      --deg[f[v]];
      f[v] = to;
      ++deg[f[v]];
    } else if (qs[i].t == 2) {
      int v = qs[i].i;
      long long cur_val = ans[v];
      for (int x : marked0) {
        if (f[x] == v || f[v] == x) {
          cur_val += t[x] / (deg[x] + 2);
        }
      }
      printf("%lld\n", cur_val + me(v));
    } else {
      assert(qs[i].t == 3);
      long long mn = min_outside;
      long long mx = max_outside;
      for (int x : all_marked) {
        cur_ans[x] = ans[x];
      }
      for (int x : all_marked) {
        if (mark0[x]) {
          cur_ans[f[x]] += t[x] / (deg[x] + 2);
        }
        if (mark0[f[x]]) {
          cur_ans[x] += t[f[x]] / (deg[f[x]] + 2);
        }
      }
      for (int x : all_marked) {
        mn = min(mn, cur_ans[x] + me(x));
        mx = max(mx, cur_ans[x] + me(x));
      }
      printf("%lld %lld\n", mn, mx);
    }
  }
}
const int K = 250;
void solve() {
  for (int l = 0; l < q;) {
    int r = l;
    int cnt = 0;
    while (r < q && cnt < K) {
      cnt += (qs[r].t == 1);
      ++r;
    }
    go(l, r);
    l = r;
  }
}
int main() {
  while (read()) {
    solve();
  }
  return 0;
}
