#include <bits/stdc++.h>
using namespace std;
template <class T>
int chkmax(T &a, T b) {
  if (b > a) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
int chkmin(T &a, T b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
template <class iterator>
void output(iterator begin, iterator end, ostream &out = cerr) {
  while (begin != end) {
    out << (*begin) << " ";
    begin++;
  }
  out << endl;
}
template <class T>
void output(T x, ostream &out = cerr) {
  output(x.begin(), x.end(), out);
}
void fast_io() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
}
const int mx = 1e5 + 228;
int n, q;
long long t[mx], give[mx], rem[mx], setVal[mx];
int par[mx], sub[mx];
vector<multiset<long long>> sets;
multiset<long long> global_max, global_min;
void formula(int v, long long &give_v, long long &rem_v) {
  give_v = t[v] / (sub[v] + 2);
  rem_v = t[v] - give_v * (sub[v] + 1);
}
void insert_to_global(int v);
void read() {
  cin >> n >> q;
  for (int i = 0; i < n; ++i) {
    cin >> t[i];
  }
  for (int i = 0; i < n; ++i) {
    cin >> par[i];
    par[i]--;
    sub[par[i]]++;
  }
  for (int i = 0; i < n; ++i) {
    formula(i, give[i], rem[i]);
    setVal[i] += rem[i];
    setVal[par[i]] += give[i];
  }
  sets.resize(n);
  for (int i = 0; i < n; ++i) {
    sets[par[i]].insert(setVal[i]);
  }
  for (int i = 0; i < n; ++i) {
    if (!sets[i].empty()) {
      insert_to_global(i);
    }
  }
}
void remove_from_global(int v) {
  if (!sets[v].empty()) {
    global_min.erase(global_min.find((*sets[v].begin()) + give[v]));
    global_max.erase(global_max.find((*prev(sets[v].end())) + give[v]));
  }
}
void insert_to_global(int v) {
  if (!sets[v].empty()) {
    global_max.insert((*prev(sets[v].end())) + give[v]);
    global_min.insert((*sets[v].begin()) + give[v]);
  }
}
void modify(int v, long long delta) {
  remove_from_global(par[v]);
  sets[par[v]].erase(sets[par[v]].find(setVal[v]));
  setVal[v] += delta;
  sets[par[v]].insert(setVal[v]);
  insert_to_global(par[v]);
}
void rehang(int u, int v, int w) {
  if (v == w) {
    return;
  }
  remove_from_global(v);
  remove_from_global(w);
  sets[v].erase(sets[v].find(setVal[u]));
  sets[w].insert(setVal[u]);
  long long new_give, new_rem;
  sub[v]--;
  formula(v, new_give, new_rem);
  long long delta_give_v = new_give - give[v];
  long long delta_rem_v = new_rem - rem[v];
  give[v] = new_give;
  rem[v] = new_rem;
  sub[w]++;
  formula(w, new_give, new_rem);
  long long delta_give_w = new_give - give[w];
  long long delta_rem_w = new_rem - rem[w];
  give[w] = new_give;
  rem[w] = new_rem;
  insert_to_global(v);
  insert_to_global(w);
  par[u] = w;
  modify(v, delta_rem_v - give[u]);
  modify(par[v], delta_give_v);
  modify(w, delta_rem_w + give[u]);
  modify(par[w], delta_give_w);
}
long long get(int v) { return setVal[v] + give[par[v]]; }
void get(long long &min, long long &max) {
  min = *global_min.begin();
  max = *prev(global_max.end());
}
void process_queries() {
  for (int i = 0; i < q; ++i) {
    int type;
    cin >> type;
    if (type == 1) {
      int u, w;
      cin >> u >> w;
      u--;
      w--;
      rehang(u, par[u], w);
    } else if (type == 2) {
      int v;
      cin >> v;
      v--;
      long long ans = get(v);
      cout << ans << '\n';
    } else if (type == 3) {
      long long min, max;
      get(min, max);
      cout << min << ' ' << max << '\n';
    }
  }
}
signed main() {
  fast_io();
  read();
  process_queries();
}
