和 Q T r e e 6 QTree6 QTree6的思路类似。
同样是两棵树,同样是维护那些信息,但是这次变成了维护最值。
那么维护虚+实的
m
x
mx
mx数组肯定是照常维护。
但是虚子树的应该怎么办呢?
考虑到涉及到撤销这个东西,所以需要
m
u
l
t
i
s
e
t
multiset
multiset
(注意删除一个值的时候,要删除地址而不是那个值)
我们可以对于每个点都开一个 m u l t i s e t multiset multiset来处理虚子树信息。
剩下的都差不多类似。
修改的时候,修改
v
a
l
val
val,记得要在
l
c
t
lct
lct上
a
c
c
e
s
s
+
s
p
l
a
y
access+splay
access+splay一下,保证能及时
u
p
d
a
t
e
update
update
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define pb push_back
#define mk make_pair
#define ll long long
#define lson ch[x][0]
#define rson ch[x][1]
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 4e5+1e2;
const int inf = 1e9+10;
const int maxm = 2*maxn;
int val[maxn];
struct lct{
int ch[maxn][2];
int mx[maxn];
multiset<int> s[maxn];
int fa[maxn];
int st[maxn];
bool notroot(int x)
{
return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
}
int son(int x)
{
if (ch[fa[x]][0]==x) return 0;
else return 1;
}
int getmax(int x)
{
if (s[x].empty()) return -inf;
else return (*s[x].rbegin());
}
void update(int x)
{
mx[x]=val[x];
//if (x==1) cout<<mx[x]<<" "<<val[x]<<" "<<val[1]<<endl;
if (ch[x][0]) mx[x]=max(mx[x],mx[ch[x][0]]);
if (ch[x][1]) mx[x]=max(mx[x],mx[ch[x][1]]);
mx[x]=max(mx[x],getmax(x));
}
void rotate(int x)
{
int y = fa[x],z = fa[y];
int b = son(x),c = son(y);
if(notroot(y)) ch[z][c]=x;
fa[x]=z;
ch[y][b]=ch[x][!b];
fa[ch[x][!b]]=y;
ch[x][!b]=y;
fa[y]=x;
update(y);
update(x);
}
void splay(int x)
{
while(notroot(x))
{
int y = fa[x],z = fa[y];
int b = son(x),c = son(y);
if (notroot(y))
{
if(b==c) rotate(y);
else rotate(x);
}
rotate(x);
}
update(x);
}
void access(int x)
{
for (int y=0;x;y=x,x=fa[x])
{
splay(x);
if (ch[x][1]) s[x].insert(mx[ch[x][1]]);
if (y) s[x].erase(s[x].find(mx[y]));
ch[x][1]=y;
update(x);
}
}
void makeroot(int x)
{
access(x);
splay(x);
}
int findroot(int x)
{
access(x);
splay(x);
while (ch[x][0]) x=ch[x][0];
return x;
}
void split(int x,int y)
{
makeroot(x);
access(y);
splay(y);
}
void link(int x,int y)
{
split(x,y);
fa[x]=y;
s[y].insert(mx[x]);
update(y);
}
void cut(int x)
{
access(x);
splay(x);
fa[ch[x][0]]=0;
ch[x][0]=0;
}
};
lct b,w;
int n,m;
int point[maxn],nxt[maxm],to[maxm];
int cnt;
int fa[maxn];
void addedge(int x,int y)
{
nxt[++cnt]=point[x];
to[cnt]=y;
point[x]=cnt;
}
void dfs(int x,int faa)
{
fa[x]=faa;
for (int i=point[x];i;i=nxt[i])
{
int p = to[i];
if (p==faa) continue;
dfs(p,x);
}
}
int col[maxn];
int main()
{
n=read();
for (int i=1;i<n;i++)
{
int x=read(),y=read();
addedge(x,y);
addedge(y,x);
}
dfs(1,n+1);
for (int i=1;i<=n;i++) col[i]=read();
for (int i=1;i<=n;i++) val[i]=read();
for (int i=1;i<=n;i++) b.mx[i]=w.mx[i]=val[i];
//cout<<val[1]<<endl;
val[n+1]=-inf;
w.mx[n+1]=b.mx[n+1]=val[n+1];
for (int i=1;i<=n;i++)
if (col[i])
b.link(i,fa[i]);
else
w.link(i,fa[i]);
m=read();
//cout<<1<<endl;
for (int i=1;i<=m;i++)
{
int opt=read();
if (opt==0)
{
int x=read();
if (col[x])
{
int roo = b.findroot(x);
b.access(x);
b.splay(roo);
cout<<b.mx[b.ch[roo][1]]<<"\n";
}
else
{
int roo = w.findroot(x);
w.access(x);
w.splay(roo);//cout<<roo<<" "<<w.ch[roo][1]<<" "<<w.mx[w.ch[roo][1]]<<" "<<val[w.ch[roo][1]]<<"****"<<endl;
cout<<w.mx[w.ch[roo][1]]<<"\n";
}
}
if (opt==1)
{
int x=read();
if (col[x])
{
b.cut(x);
col[x]=0;
w.link(x,fa[x]);
}
else
{
col[x]=1;
w.cut(x);
b.link(x,fa[x]);
}
}
if (opt==2)
{
int x=read(),y=read();
//val[x]=y;
if (col[x])
{
b.access(x);
b.splay(x);
val[x]=y;
}
else
{
w.access(x);
w.splay(x);
val[x]=y;
}
}
}
return 0;
}