题意:
给你一个
n
n
n个点的树,每个点有点权和一个颜色,颜色是黑白之一。有
m
m
m次操作,每次有三种可能的操作,第一种是修改一个点的颜色,第二种是修改一个点的权值,第三个是给你一个
x
x
x,问所有到
x
x
x路径上颜色全相同点的最大权值。
n
,
m
<
=
1
e
5
n,m<=1e5
n,m<=1e5。
题解:
和QTREE6差不多,但是这次是维护子树最大值。我们在之前的思路上进行改进。我们知道,用LCT维护虚子树的话,一般是要用set或者multiset来维护的。我们对每个点开一个multiset,在每个multiset里维护这个点的所有虚子树的子树最大值,在虚实子树切换的时候更改一下,也就是在link和access的时候要改变multiset里的元素。然后注意一下multiset是空集的时候。其他的就和QTREE6差不多,就不多说了。
代码:
#include <bits/stdc++.h>
using namespace std;
int n,m,hed[200010],cnt,col[200010],val[200010],fa[200010];
struct edge
{
int to,next;
}a[400010];
struct LCT
{
int f[200010],c[200010][2],val[200010],mx[200010];
multiset<int> s[200010];
inline int nroot(int x)
{
return c[f[x]][0]==x||c[f[x]][1]==x;
}
inline void pushup(int x)
{
mx[x]=val[x];
if(c[x][0])
mx[x]=max(mx[x],mx[c[x][0]]);
if(c[x][1])
mx[x]=max(mx[x],mx[c[x][1]]);
if(!s[x].empty())
mx[x]=max(mx[x],(*(--s[x].end())));
}
inline void rotate(int x)
{
int y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
if(nroot(y))
c[z][c[z][1]==y]=x;
c[x][!k]=y;
c[y][k]=w;
if(w)
f[w]=y;
f[y]=x;
f[x]=z;
pushup(y);
pushup(x);
}
inline void splay(int x)
{
while(nroot(x))
{
int y=f[x],z=f[y];
if(nroot(y))
{
if(c[z][1]==y^c[y][1]==x)
rotate(x);
else
rotate(y);
}
rotate(x);
}
pushup(x);
}
inline void access(int x)
{
int y=0;
while(x)
{
splay(x);
if(y)
s[x].erase(s[x].find(mx[y]));
if(c[x][1])
s[x].insert(mx[c[x][1]]);
c[x][1]=y;
if(y)
f[y]=x;
pushup(x);
y=x;
x=f[x];
}
}
inline void link(int x,int y)
{
access(x);
splay(x);
access(y);
splay(y);
f[x]=y;
s[y].insert(mx[x]);
pushup(y);
}
inline void cut(int x)
{
access(x);
splay(x);
f[c[x][0]]=0;
c[x][0]=0;
}
inline int find(int x)
{
access(x);
splay(x);
while(c[x][0])
x=c[x][0];
return x;
}
}b,w;
inline int read()
{
int x=0,f=1;
char s=getchar();
while(s>'9'||s<'0')
{
if(s=='-')
f=-1;
s=getchar();
}
while(s>='0'&&s<='9')
{
x=x*10+s-'0';
s=getchar();
}
return x*f;
}
inline void add(int from,int to)
{
a[++cnt].to=to;
a[cnt].next=hed[from];
hed[from]=cnt;
}
inline void dfs(int x)
{
for(int i=hed[x];i;i=a[i].next)
{
int y=a[i].to;
if(y==fa[x])
continue;
fa[y]=x;
dfs(y);
}
}
int main()
{
n=read();
for(int i=1;i<=n-1;++i)
{
int x=read(),y=read();
add(x,y);
add(y,x);
}
for(int i=1;i<=n;++i)
col[i]=read();
for(int i=1;i<=n;++i)
val[i]=read();
fa[1]=n+1;
dfs(1);
b.val[n+1]=-2e9;
b.mx[n+1]=-2e9;
w.val[n+1]=-2e9;
w.mx[n+1]=-2e9;
for(int i=1;i<=n;++i)
{
b.val[i]=val[i];
w.val[i]=val[i];
b.mx[i]=val[i];
w.mx[i]=val[i];
}
for(int i=1;i<=n;++i)
{
if(col[i])
b.link(i,fa[i]);
else
w.link(i,fa[i]);
}
m=read();
for(int i=1;i<=m;++i)
{
int opt=read(),x=read();
if(opt==0)
{
if(col[x])
{
int y=b.find(x);
b.access(x);
b.splay(y);
printf("%d\n",b.mx[b.c[y][1]]);
}
else
{
int y=w.find(x);
w.access(x);
w.splay(y);
printf("%d\n",w.mx[w.c[y][1]]);
}
}
else if(opt==1)
{
if(col[x])
{
col[x]=0;
b.cut(x);
w.link(x,fa[x]);
}
else
{
col[x]=1;
w.cut(x);
b.link(x,fa[x]);
}
}
else
{
int y=read();
b.access(x);
b.splay(x);
b.val[x]=y;
w.access(x);
w.splay(x);
w.val[x]=y;
}
}
return 0;
}