传送门
解析:
还是和前面六道差不多的套路,放弃makeroot,连父亲,用根的右儿子表示当前联通块,开一个multiset维护虚子树的信息,access的时候切换一下。
只需要在更新权值的时候在两个LCT里面都更新一下信息就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
re bool f=0;
while(!isdigit(c=gc()))if(c=='-')f=1;re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return f?-num:num;
}
}
using namespace IO;
cs int N=1e5+5;
int n;
int last[N],nxt[N<<1],to[N<<1],ecnt;
inline void addedge(int u,int v){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v;
nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u;
}
inline int fir(cs std::multiset<int> &s){return s.empty()?-0x3f3f3f3f:*s.rbegin();}
int val[N],fa[N];
struct LCT{
int fa[N],son[N][2],mx[N];
std::multiset<int> s[N];
LCT(){mx[0]=-0x3f3f3f3f;}
void pushup(int u){mx[u]=std::max(std::max(fir(s[u]),val[u]),std::max(mx[son[u][0]],mx[son[u][1]]));}
bool which(int u){return son[fa[u]][1]==u;}
bool isroot(int u){return son[fa[u]][0]!=u&&son[fa[u]][1]!=u;}
void Rotate(int u){
int Fa=fa[u],FA=fa[Fa];
bool pos=which(u);
if(!isroot(Fa))son[FA][which(Fa)]=u;
son[Fa][pos]=son[u][!pos];
son[u][!pos]=Fa;
if(son[Fa][pos])fa[son[Fa][pos]]=Fa;
fa[Fa]=u;fa[u]=FA;
pushup(Fa);pushup(u);
}
void Splay(int u){
for(int re Fa=fa[u];!isroot(u);Rotate(u),Fa=fa[u])
if(!isroot(Fa))Rotate(which(Fa)==which(u)?Fa:u);
}
void access(int u){
for(int re ch=0;u;u=fa[ch=u]){
Splay(u);
if(son[u][1])s[u].insert(mx[son[u][1]]);
if(ch)s[u].erase(s[u].find(mx[ch]));
son[u][1]=ch;
pushup(u);
}
}
void link(int u,int v){
access(v),Splay(v);
Splay(u);
son[fa[u]=v][1]=u;
pushup(v);
}
void cut(int u,int v){
access(u);
Splay(u);
fa[son[u][0]]=0;
son[u][0]=0;
pushup(u);
}
int query(int u){
access(u);
Splay(u);
while(son[u][0])u=son[u][0];
Splay(u);
return mx[son[u][1]];
}
}t[2];
bool col[N];
void dfs(int u){
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]])if(v!=fa[u]){
t[col[v]].link(v,fa[v]=u);
dfs(v);
}
}
signed main(){
n=getint();
for(int re i=1;i<n;++i)addedge(getint(),getint());
for(int re i=1;i<=n;++i)col[i]=getint();
for(int re i=1;i<=n;++i)t[0].mx[i]=t[1].mx[i]=val[i]=getint();
dfs(1);fa[1]=n+1;
t[col[1]].link(1,fa[1]);
int m=getint();
while(m--){
switch(getint()){
case 0:{
int u=getint();
std::cout<<t[col[u]].query(u)<<"\n";
break;
}
case 1:{
int u=getint();
t[col[u]].cut(u,fa[u]);
col[u]^=1;
t[col[u]].link(u,fa[u]);
break;
}
case 2:{
int u=getint();
t[0].access(u),t[1].access(u);
t[0].Splay(u),t[1].Splay(u);
val[u]=getint();
t[0].pushup(u),t[1].pushup(u);
break;
}
}
}
return 0;
}