#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;   }