#include <bits/stdc++.h>
using namespace std;
const long long INF = 1e17, Mo = INF + 7;
const int N = 100000;
const double eps = 1e-6;
namespace slow_IO {
long long read() {
  long long x = 0;
  int zf = 1;
  char ch = getchar();
  while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
  if (ch == '-') zf = -1, ch = getchar();
  while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
  return x * zf;
}
void write(long long y) {
  if (y < 0) putchar('-'), y = -y;
  if (y > 9) write(y / 10);
  putchar(y % 10 + '0');
}
}  // namespace slow_IO
namespace fast_IO {
inline char read() {
  return getchar();
  static const int IN_LEN = 1000000;
  static char buf[IN_LEN], *s, *t;
  if (s == t) {
    t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
    if (s == t) return -1;
  }
  return *s++;
}
template <class T>
inline void read(T &x) {
  static bool iosig;
  static char c;
  for (iosig = false, c = read(); !isdigit(c); c = read()) {
    if (c == '-') iosig = true;
    if (c == -1) return;
  }
  for (x = 0; isdigit(c); c = read()) x = ((x + (x << 2)) << 1) + (c ^ '0');
  if (iosig) x = -x;
}
const int OUT_LEN = 10000000;
char obuf[OUT_LEN], *ooh = obuf;
inline void print(char c) {
  if (ooh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), ooh = obuf;
  *ooh++ = c;
}
template <class T>
inline void print(T x) {
  static int buf[30], cnt;
  if (x == 0)
    print('0');
  else {
    if (x < 0) print('-'), x = -x;
    for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
    while (cnt) print((char)buf[cnt--]);
  }
}
inline void flush() { fwrite(obuf, 1, ooh - obuf, stdout); }
}  // namespace fast_IO
using namespace slow_IO;
multiset<long long> Set1, Set2, Set[N + 5];
long long A[N + 5], B[N + 5], D[N + 5], E[N + 5], Ans[N + 5];
void Change1(int t) {
  multiset<long long>::iterator it;
  if (Set[t].begin() == Set[t].end()) return;
  it = Set1.find(*Set[t].begin() + E[t]);
  if (it != Set1.end()) Set1.erase(it);
  it = Set2.find(*Set[t].rbegin() + E[t]);
  if (it != Set2.end()) Set2.erase(it);
}
void Change2(int t) {
  if (Set[t].begin() != Set[t].end()) {
    Set1.insert(*Set[t].begin() + E[t]);
    Set2.insert(*Set[t].rbegin() + E[t]);
  }
}
void Delete(int t) {
  multiset<long long>::iterator it = Set[A[t]].find(Ans[t]);
  if (it != Set[A[t]].end()) Set[A[t]].erase(it);
}
void Insert(int t) { Set[A[t]].insert(Ans[t]); }
int main() {
  int n = read(), q = read();
  for (int i = (1); i <= (n); i++) B[i] = read();
  for (int i = (1); i <= (n); i++) A[i] = read(), D[i] = 2;
  for (int i = (1); i <= (n); i++) D[A[i]]++;
  for (int i = (1); i <= (n); i++)
    E[i] = B[i] / D[i], Ans[i] = E[i] + B[i] % D[i];
  for (int i = (1); i <= (n); i++) Ans[A[i]] += E[i];
  for (int i = (1); i <= (n); i++) Insert(i);
  for (int i = (1); i <= (n); i++)
    if (Set[i].begin() != Set[i].end()) Change2(i);
  while (q--) {
    int op = read();
    if (op == 1) {
      int x = read(), y = read();
      int z = A[x];
      Change1(A[A[y]]);
      Delete(A[y]);
      Change1(A[y]);
      Delete(y);
      Change1(y);
      Ans[y] -= E[y] + B[y] % D[y], Ans[A[y]] -= E[y];
      D[y]++;
      E[y] = B[y] / D[y];
      Ans[y] += E[x];
      Ans[y] += E[y] + B[y] % D[y], Ans[A[y]] += E[y];
      Change2(y);
      Insert(y);
      Change2(A[y]);
      Insert(A[y]);
      Change2(A[A[y]]);
      Change1(z), Change1(y);
      Delete(x);
      A[x] = y;
      Insert(x);
      Change2(z), Change2(y);
      Change1(A[A[z]]);
      Delete(A[z]);
      Change1(A[z]);
      Delete(z);
      Change1(z);
      Ans[z] -= E[z] + B[z] % D[z], Ans[A[z]] -= E[z];
      D[z]--;
      E[z] = B[z] / D[z];
      Ans[z] -= E[x];
      Ans[z] += E[z] + B[z] % D[z], Ans[A[z]] += E[z];
      Change2(z);
      Insert(z);
      Change2(A[z]);
      Insert(A[z]);
      Change2(A[A[z]]);
    } else if (op == 2) {
      int x = read();
      printf("%I64d\n", Ans[x] + E[A[x]]);
    } else {
      printf("%I64d %I64d\n", *Set1.begin(), *Set2.rbegin());
    }
  }
}
