#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXV = 4e6 + 5;
const int MAXN = 2e6 + 5;
int val[MAXV];
int tin[MAXV], tout[MAXV], depth[MAXV];
/*int anc[MAXN][21];
int myanc(int x, int d)
{
for(int b=0;b<21;b++)
if((1<<b)&d)
x = anc[x][b];
return x;
}*/
struct GROUP
{
vector<int> aib;
int qry_aib(int poz)
{
poz++;
int sum = 0;
for(int i=poz;i>0;i-=(i&(-i)))
sum += aib[i];
return sum;
}
void upd_aib(int poz, int newv)
{
poz++;
for(int i=poz;i<aib.size();i+=(i&(-i)))
aib[i] += newv;
}
int lazy_up = -1;
int my_depth;
vector<pair<int,int>> nodes;//{tin, nod} sorted after tin
void init(vector<pair<int,int>> myv, int init_depth)
{
nodes = myv;
lazy_up = my_depth = init_depth;
aib.resize(nodes.size() + 3, 0);
for(int i=0;i<nodes.size();i++)
upd_aib(i, val[nodes[i].second]);
}
};
int who[MAXN];//who[d] = which group is on depth d
GROUP comp[MAXV];
void unite(int idx, int idy, int newd)//merge the group with idy into the group with idx
{
assert(who[newd] == idx);
assert(comp[idx].my_depth != comp[idy].my_depth);
if(comp[idx].my_depth > comp[idy].my_depth)
{
who[newd] = idy;
swap(idx, idy);
}
for(auto [mytin,y]:comp[idy].nodes)
{
int poz = lower_bound(comp[idx].nodes.begin(), comp[idx].nodes.end(), make_pair(mytin, 0LL)) - comp[idx].nodes.begin() - 1;
assert(0 <= poz && poz < comp[idx].nodes.size());
comp[idx].upd_aib(poz, val[y]);
val[comp[idx].nodes[poz].second] += val[y];
val[y] = 0;
}
}
int query(int id, int init_nod)
{
int le = lower_bound(comp[id].nodes.begin(), comp[id].nodes.end(), make_pair(tin[init_nod], 0LL)) - comp[id].nodes.begin();
int ri = lower_bound(comp[id].nodes.begin(), comp[id].nodes.end(), make_pair(tout[init_nod] + 1, 0LL)) - comp[id].nodes.begin() - 1;
return comp[id].qry_aib(ri) - comp[id].qry_aib(le - 1);
}
int n, timer;
int parent[MAXN];
vector<int> con[MAXN];
vector<pair<int,int>> ofdepth[MAXN];
void dfs(int nod)
{
tin[nod] = ++timer;
for(int adj:con[nod])
{
depth[adj] = depth[nod] + 1;
dfs(adj);
}
tout[nod] = timer;
}
signed main()
{
ios_base::sync_with_stdio(0);cin.tie(0);
cin>>n;
for(int i=2;i<=n;i++)
{
cin>>parent[i];
con[parent[i]].push_back(i);
}
for(int i=1;i<=n;i++)
cin>>val[i];
dfs(1);
for(int i=1;i<=n;i++)
ofdepth[depth[i]].push_back({tin[i], i});
for(int d=0;d<n;d++)
{
if(ofdepth[d].empty())
{
who[d] = -1;
}
else
{
sort(ofdepth[d].begin(), ofdepth[d].end());
who[d] = d;
comp[d].init(ofdepth[d], d);
}
}
int q;
cin>>q;
while(q--)
{
int tip;
cin>>tip;
if(tip == 1)
{
int x,y;
cin>>x>>y;
swap(x, y);
assert(x < y);
if(who[y] == -1)
continue;
if(who[x] == -1)
{
comp[who[y]].lazy_up = x;
who[x] = who[y];
who[y] = -1;
}
else
{
unite(who[x], who[y], x);
who[y] = -1;
}
}
else if(tip == 2)
{
}
else
{
assert(tip == 3);
int b;
cin>>b;
if(who[depth[b]] == -1)
cout<<0<<"\n";
else
cout<<query(who[depth[b]], b)<<"\n";
}
}
return 0;
}