#include <bits/stdc++.h>
#define inf 2147483547
#define ll long long
#define o1(x) id[x]-1
#define o2(x) id[x]+sz[x]
using namespace std;
const int N=400010;
struct edge
{
int next,to;
}e[N<<1];
int n,cnt,root,dfn;
struct Tree
{
ll sum,mmin,mmax,set,add;
}a[N<<2];
int sz[N],head[N],son[N],top[N],id[N],c[N],dep[N],f[N],num[N];
inline ll mmax(ll lo,ll ro)
{
ll a=lo,b=ro;
return max(a,b);
}
inline ll mmin(ll lo,ll ro)
{
ll a=lo,b=ro;
return min(a,b);
}
inline ll read()
{
char ch=getchar();
ll num=0,flag=1;
while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){num=(num<<3)+(num<<1)+ch-'0';ch=getchar();}
return flag*num;
}
inline void print(ll x)
{
static int cnt;
static int a[15];
cnt=0;
do
{
a[++cnt]=x%10;
x/=10;
}while(x);
for(int i=cnt;i>=1;i--)putchar(a[i]+'0');
puts("");
}
inline void add(int x,int y)
{
e[++cnt].to=y;
e[cnt].next=head[x];
head[x]=cnt;
}
inline void dfs1(int x,int fa)
{
sz[x]=1;
dep[x]=dep[fa]+1;
f[x]=fa;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[v]>sz[son[x]])son[x]=v;
}
}
inline void dfs2(int x,int tp)
{
top[x]=tp;
id[x]=++dfn;
num[dfn]=x;
if(son[x])dfs2(son[x],tp);
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v!=son[x])dfs2(v,v);
}
}
inline void up(ll p,ll l,ll r)
{
ll lc=p<<1,rc=(p<<1)+1;
if(r>l)
{
a[p].mmax=mmax(a[lc].mmax,a[rc].mmax);
a[p].mmin=mmin(a[lc].mmin,a[rc].mmin);
a[p].sum=a[lc].sum+a[rc].sum;
}
}
inline void down(ll p,ll l,ll r)
{
ll lc=p<<1,rc=(p<<1)+1,m=l+((r-l)>>1);
if(a[p].set!=inf)
{
a[lc].mmax=a[rc].mmax=a[lc].mmin=a[rc].mmin=a[lc].set=a[rc].set=a[p].set;
a[lc].sum=(m-l+1)*a[p].set;
a[rc].sum=(r-m)*a[p].set;
a[p].set=inf;
a[lc].add=a[rc].add=a[p].add=0;
}
if(a[p].add)
{
if(a[lc].set==inf)a[lc].add+=a[p].add;else a[lc].set+=a[p].add;
if(a[rc].set==inf)a[rc].add+=a[p].add;else a[rc].set+=a[p].add;
a[lc].mmin+=a[p].add,a[rc].mmin+=a[p].add,
a[lc].mmax+=a[p].add,a[rc].mmax+=a[p].add,
a[lc].sum+=(m-l+1)*a[p].add,
a[rc].sum+=(r-m)*a[p].add,
a[p].add=0;
}
}
inline void build(ll p,ll l,ll r)
{
if(l==r)
{
int x=c[num[l]];
a[p]=(Tree){x,x,x,-1,0};
return;
}
ll m=l+((r-l)>>1),lc=p<<1,rc=(p<<1)+1;
build(lc,l,m);
build(rc,m+1,r);
a[p].set=inf;
up(p,l,r);
return;
}
inline void update_add(ll p,ll l,ll r,ll lp,ll rp,ll v)
{
ll lc=p<<1,rc=(p<<1)+1;
if(lp<=l&&r<=rp)
{
a[p].mmax+=v;
a[p].mmin+=v;
a[p].sum+=(r-l+1)*v;
if(a[p].set!=inf)
{
a[p].set+=v;return;
}
a[p].add+=v;
}
else
{
ll m=l+((r-l)>>1);
down(p,l,r);
if(lp<=m)update_add(lc,l,m,lp,rp,v);
if(rp>m)update_add(rc,m+1,r,lp,rp,v);
up(p,l,r);
}
}
inline void update_set(ll p,ll l,ll r,ll lp,ll rp,ll v)
{
ll lc=p<<1,rc=(p<<1)+1;
if(lp<=l&&r<=rp)
{
a[p].mmin=a[p].mmax=a[p].set=v;
a[p].sum=(r-l+1)*v,a[p].add=0;
}
else
{
down(p,l,r);
ll m=l+((r-l)>>1);
if(lp<=m)update_set(lc,l,m,lp,rp,v);
if(rp>m)update_set(rc,m+1,r,lp,rp,v);
up(p,l,r);
}
}
inline ll query_sum(ll p,ll l,ll r,ll lp,ll rp)
{
if(lp<=l&&r<=rp)return a[p].sum;
ll m=l+((r-l)>>1),lc=p<<1,rc=(p<<1)+1,ans=0;
down(p,l,r);
if(lp<=m)ans+=query_sum(lc,l,m,lp,rp);
if(rp>m)ans+=query_sum(rc,m+1,r,lp,rp);
return ans;
}
inline ll query_max(ll p,ll l,ll r,ll lp,ll rp)
{
if(lp<=l&&r<=rp)return a[p].mmax;
ll m=l+((r-l)>>1),lc=p<<1,rc=(p<<1)+1,ans=-0x7f3f3f3f;
down(p,l,r);
if(lp<=m)ans=mmax(ans,query_max(lc,l,m,lp,rp));
if(rp>m)ans=mmax(ans,query_max(rc,m+1,r,lp,rp));
return ans;
}
inline ll query_min(ll p,ll l,ll r,ll lp,ll rp)
{
if(lp<=l&&r<=rp)return a[p].mmin;
ll m=l+((r-l)>>1),lc=p<<1,rc=(p<<1)+1,ans=0x7f3f3f3f;
down(p,l,r);
if(lp<=m)ans=mmin(ans,query_min(lc,l,m,lp,rp));
if(rp>m)ans=mmin(ans,query_min(rc,m+1,r,lp,rp));
return ans;
}
inline void update_add_path(int x,int y,ll k)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
update_add(1,1,n,id[top[x]],id[x],k);
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
update_add(1,1,n,id[y],id[x],k);
}
inline void update_set_path(int x,int y,ll k)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
update_set(1,1,n,id[top[x]],id[x],k);
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
update_set(1,1,n,id[y],id[x],k);
}
inline ll query_sum_path(int x,int y)
{
ll ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans+=query_sum(1,1,n,id[top[x]],id[x]);
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans+=query_sum(1,1,n,id[y],id[x]);
return ans;
}
inline ll query_max_path(int x,int y)
{
ll ans=-inf;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=mmax(ans,query_max(1,1,n,id[top[x]],id[x]));
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans=mmax(ans,query_max(1,1,n,id[top[x]],id[x]));
return ans;
}
inline ll query_min_path(int x,int y)
{
ll ans=inf;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=mmin(ans,query_min(1,1,n,id[top[x]],id[x]));
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans=mmin(ans,query_min(1,1,n,id[top[x]],id[x]));
return ans;
}
inline int check(int x)
{
if(x==root)return -1;
if(!(id[root]>=id[x]&&id[root]<id[x]+sz[x]))return 0;
int now=root;
while(dep[now]>dep[x])
{
if(f[top[now]]==x)return top[now];
now=f[top[now]];
}
return son[x];
}
inline void update_add_tree(int x,ll k)
{
int p=check(x);
if(p==-1)update_add(1,1,n,1,n,k);
else if(p==0)update_add(1,1,n,o1(x)+1,o2(x)-1,k);
else{update_add(1,1,n,1,o1(p),k);update_add(1,1,n,o2(p),n,k);}
}
inline void update_set_tree(int x,ll k)
{
int p=check(x);
if(p==-1)update_set(1,1,n,1,n,k);
else if(p==0)update_set(1,1,n,o1(x)+1,o2(x)-1,k);
else{update_set(1,1,n,1,o1(p),k);update_set(1,1,n,o2(p),n,k);}
}
inline ll query_sum_tree(int x)
{
int p=check(x);
if(p==-1)return query_sum(1,1,n,1,n);
else if(p==0)return query_sum(1,1,n,o1(x)+1,o2(x)-1);
else return query_sum(1,1,n,1,o1(p))+query_sum(1,1,n,o2(p),n);
}
inline ll query_max_tree(int x)
{
int p=check(x);
if(p==-1)return query_max(1,1,n,1,n);
else if(p==0)return query_max(1,1,n,o1(x)+1,o2(x)-1);
else return mmax(query_max(1,1,n,1,o1(p)),query_max(1,1,n,o2(p),n));
}
inline ll query_min_tree(int x)
{
int p=check(x);
if(p==-1)return query_min(1,1,n,1,n);
else if(p==0)return query_min(1,1,n,o1(x)+1,o2(x)-1);
else return mmin(query_min(1,1,n,1,o1(p)),query_min(1,1,n,o2(p),n));
}
int opt,x,y,Q;
ll k;
int main()
{
n=read();
for (int i=1;i<=n;i++)c[i]=read();
for (int i=2;i<=n;i++)x=read(),add(x,i);
dfs1(1,0);dfs2(1,1);
build(1,1,n);
root=1;
Q=read();
while(Q--)
{
opt=read();x=read();
if(opt==1)root=x;
else if(opt==2){y=read(); k=read(); update_add_path(x,y,k);}
else if(opt==3){k=read(); update_add_tree(x,k);}
else if(opt==4){y=read(); print(query_sum_path(x,y));}
else if(opt==5)printf("%lld\n",query_sum_tree(x));
else if(opt==6){y=read(); k=read(); update_set_path(x,y,k);}
else if(opt==7){k=read(); update_set_tree(x,k);}
else if(opt==8){y=read(); print(query_max_path(x,y));}
else if(opt==9){y=read(); print(query_min_path(x,y));}
else if(opt==10)printf("%lld\n",query_max_tree(x));
else if(opt==11)printf("%lld\n",query_min_tree(x));
}
return 0;
}