每一个
s
p
l
a
y
splay
splay的节点记录
a
n
s
l
ansl
ansl和
a
n
s
r
ansr
ansr,分别记录从它所管辖的链区间的链顶和链底出发的最长路径。开一个
m
u
l
t
i
s
e
t
multiset
multiset维护虚子树的
a
n
s
l
ansl
ansl。
一个点的转移就是:从链顶/底出发,不经过这个点?经过这个点穿进虚子树?经过这个点穿到下面去?这三种情况。
询问点
u
u
u,就是
a
c
c
e
s
s
access
access之后
u
u
u成为链底,询问一下它延伸出的最长路径即可。
初始化的时候从下往上要
p
u
s
h
u
p
pushup
pushup一下。
#include<bits/stdc++.h>
#define re register
#define cs const
using std::max;
using std::swap;
cs int N=1e5+10,oo=1e9+10;
int n,m,u,v,op,val[N];
inline void Max(int &x,int y){if(x<y)x=y;}
namespace IO{
cs int Rlen=1<<22|1;
char buf[Rlen],*p1,*p2;
inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
template<typename T>
inline T get(){
char ch=gc();T x=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
while(isdigit(ch)) x=((x+(x<<2))<<1)+(ch^48),ch=gc();
return x*f;
}
inline int gi(){return get<int>();}
}
using IO::gi;
std::multiset<int> S[N];
namespace LCT{
int son[N][2],fa[N],sum[N];
int ansl[N],ansr[N];
inline int get(int x){return x==son[fa[x]][1];}
inline int isroot(int x){return (!fa[x])||(x!=son[fa[x]][0]&&x!=son[fa[x]][1]);}
inline int top(int x){return S[x].empty()?-oo:*S[x].rbegin();}
inline void pushup(int x){
sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x];
ansl[x]=max(ansl[son[x][0]],sum[son[x][0]]+val[x]+max(0,max(top(x),ansl[son[x][1]])));
ansr[x]=max(ansr[son[x][1]],sum[son[x][1]]+val[x]+max(0,max(top(x),ansr[son[x][0]])));
}
inline void rotate(int x){
int y=fa[x],z=fa[y],k=get(x),l=son[x][k^1];
fa[x]=z;if(!isroot(y)) son[z][get(y)]=x;
fa[y]=x,son[x][k^1]=y,fa[l]=y,son[y][k]=l;
pushup(y),pushup(x);
}
inline void splay(int x){
for(int re y=fa[x];!isroot(x);rotate(x),y=fa[x])
if(!isroot(y)) rotate(get(y)==get(x)?y:x);
}
inline void access(int x){
for(int re y=0;x;x=fa[y=x]){
splay(x);
if(son[x][1]) S[x].insert(ansl[son[x][1]]);
if(y) S[x].erase(S[x].find(ansl[y]));
son[x][1]=y,pushup(x);
}
}
}
using namespace LCT;
int main(){
// freopen("3371.in","r",stdin);
n=gi(),m=gi(),ansl[0]=ansr[0]=-oo;
for(int re i=2;i<=n;++i) fa[i]=gi();
for(int re i=1;i<=n;++i) val[i]=gi();
for(int re i=n;i>=1;--i) pushup(i),S[fa[i]].insert(ansl[i]);
while(m--){
op=gi();
if(op==1) u=gi(),access(u),splay(u),printf("%d\n",ansr[u]);
if(op==2) u=gi(),v=gi(),access(u),splay(u),val[u]=v;
}
}