#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int n, q;
int f[MAXN];
long long t[MAXN];
set<pair<long long, int> > seta[MAXN];
unordered_map<int, long long> child_profit[MAXN];
long long child_sum[MAXN];
set<pair<long long, int> > global_seta_min, global_seta_max;
long long minAns[MAXN];
long long maxAns[MAXN];
const long long inf = 1e18;
void init() {
  for (int i = 1; i < n + 1; ++i) {
    child_sum[i] = 0;
  }
}
void preprocess() {
  for (int i = 1; i < n + 1; ++i) {
    long long aroundProfit = t[i] / (seta[i].size() + 2);
    long long ownProfit = t[i] - (seta[i].size() + 1) * aroundProfit;
    for (auto item : seta[i])
      child_sum[i] += t[item.second] / (seta[item.second].size() + 2);
    seta[f[i]].erase(make_pair(0, i));
    child_profit[f[i]][i] = ownProfit + child_sum[i];
    seta[f[i]].insert(make_pair(child_profit[f[i]][i], i));
  }
  for (int u = 1; u < n + 1; ++u) {
    long long delta = t[u] / (seta[u].size() + 2);
    minAns[u] = (seta[u].size() > 0) ? (seta[u].begin()->first + delta) : inf;
    maxAns[u] = (seta[u].size() > 0) ? (seta[u].rbegin()->first + delta) : 0;
    global_seta_min.insert(make_pair(minAns[u], u));
    global_seta_max.insert(make_pair(maxAns[u], u));
  }
}
void updateMinMax(int u) {
  global_seta_min.erase(make_pair(minAns[u], u));
  global_seta_max.erase(make_pair(maxAns[u], u));
  long long delta = t[u] / (seta[u].size() + 2);
  minAns[u] = (seta[u].size() > 0) ? seta[u].begin()->first + delta : inf;
  maxAns[u] = (seta[u].size() > 0) ? seta[u].rbegin()->first + delta : 0;
  global_seta_min.insert(make_pair(minAns[u], u));
  global_seta_max.insert(make_pair(maxAns[u], u));
}
long long calcProfitWithoutParent(int u) {
  return child_sum[u] + t[u] -
         (seta[u].size() + 1) * (t[u] / (seta[u].size() + 2));
}
void solve() {
  scanf("%d%d", &n, &q);
  init();
  for (int i = 1; i < n + 1; ++i) scanf("%I64d", &t[i]);
  for (int i = 1; i < n + 1; ++i) {
    scanf("%I64d", &f[i]);
    seta[f[i]].insert(make_pair(0, i));
    child_profit[f[i]][i] = 0;
  }
  preprocess();
  long long profit;
  int newF, oldF;
  for (int i = 0; i < q; ++i) {
    int type;
    scanf("%d", &type);
    switch (type) {
      case 1:
        int a, b;
        scanf("%d%d", &a, &b);
        oldF = f[a];
        newF = b;
        child_sum[oldF] -= t[a] / (seta[a].size() + 2);
        child_sum[f[oldF]] -= t[oldF] / (seta[oldF].size() + 2);
        seta[oldF].erase(make_pair(child_profit[oldF][a], a));
        child_profit[oldF].erase(a);
        child_sum[f[oldF]] += t[oldF] / (seta[oldF].size() + 2);
        seta[f[f[oldF]]].erase(
            make_pair(child_profit[f[f[oldF]]][f[oldF]], f[oldF]));
        child_profit[f[f[oldF]]][f[oldF]] = calcProfitWithoutParent(f[oldF]);
        seta[f[f[oldF]]].insert(
            make_pair(child_profit[f[f[oldF]]][f[oldF]], f[oldF]));
        seta[f[oldF]].erase(make_pair(child_profit[f[oldF]][oldF], oldF));
        child_profit[f[oldF]][oldF] = calcProfitWithoutParent(oldF);
        seta[f[oldF]].insert(make_pair(child_profit[f[oldF]][oldF], oldF));
        updateMinMax(f[f[oldF]]);
        updateMinMax(f[oldF]);
        updateMinMax(oldF);
        child_sum[newF] += t[a] / (seta[a].size() + 2);
        child_sum[f[newF]] -= t[newF] / (seta[newF].size() + 2);
        child_profit[newF].insert(make_pair(a, calcProfitWithoutParent(a)));
        seta[newF].insert(make_pair(child_profit[newF][a], a));
        child_sum[f[newF]] += t[newF] / (seta[newF].size() + 2);
        seta[f[f[newF]]].erase(
            make_pair(child_profit[f[f[newF]]][f[newF]], f[newF]));
        child_profit[f[f[newF]]][f[newF]] = calcProfitWithoutParent(f[newF]);
        seta[f[f[newF]]].insert(
            make_pair(child_profit[f[f[newF]]][f[newF]], f[newF]));
        seta[f[newF]].erase(make_pair(child_profit[f[newF]][newF], newF));
        child_profit[f[newF]][newF] = calcProfitWithoutParent(newF);
        seta[f[newF]].insert(make_pair(child_profit[f[newF]][newF], newF));
        updateMinMax(f[f[newF]]);
        updateMinMax(f[newF]);
        updateMinMax(newF);
        f[a] = newF;
        break;
      case 2:
        int x;
        scanf("%d", &x);
        profit = t[x] - (seta[x].size() + 1) * (t[x] / (seta[x].size() + 2)) +
                 child_sum[x] + t[f[x]] / (seta[f[x]].size() + 2);
        printf("%I64d\n", profit);
        break;
      case 3:
        printf("%I64d %I64d\n", global_seta_min.begin()->first,
               global_seta_max.rbegin()->first);
        break;
    }
  }
}
int main() {
  solve();
  return 0;
}
