题意:有一棵树,节点有黑白两种颜色,带点权,三种操作:反转颜色,修改点权,询问同色连通块中的最大点权
得温习一下lct了...
维护黑白两棵lct,multiset维护子树信息即可,反转颜色就是一种颜色cut另一种颜色link
根的处理比较麻烦,但我们可以在建lct的时候让每棵lct中含有最多一个非同色点(并且是深度最浅的),查询时特判一下即可,这样做的好处就是翻转根的颜色时不用特判
#include<stdio.h>
#include<set>
using namespace std;
const int inf=2147483647;
int c[100010];
struct lct{
int fa[100010],ch[100010][2],v[100010],mx[100010];
multiset<int>ms[100010];
#define ls ch[x][0]
#define rs ch[x][1]
lct(){mx[0]=-inf;}
int vmax(int x){return ms[x].empty()?-inf:*ms[x].rbegin();}
void pushup(int x){
mx[x]=max(max(mx[ls],mx[rs]),max(v[x],vmax(x)));
}
void rot(int x){
int y,z,f,b;
y=fa[x];
z=fa[y];
f=ch[y][0]==x;
b=ch[x][f];
fa[x]=z;
fa[y]=x;
if(b)fa[b]=y;
ch[x][f]=y;
ch[y][f^1]=b;
if(ch[z][0]==y)ch[z][0]=x;
if(ch[z][1]==y)ch[z][1]=x;
pushup(y);
pushup(x);
}
bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void splay(int x){
int y,z;
while(!isrt(x)){
y=fa[x];
z=fa[y];
if(!isrt(y))rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x);
rot(x);
}
}
void access(int x){
int y=0;
while(x){
splay(x);
if(rs)ms[x].insert(mx[rs]);
rs=y;
if(y)ms[x].erase(ms[x].find(mx[y]));
pushup(x);
y=x;
x=fa[x];
}
}
void link(int x,int y){//x=fa[y]
access(x);
splay(x);
splay(y);
fa[y]=x;
rs=y;
pushup(x);
}
void cut(int x){
access(x);
splay(x);
fa[ls]=0;
ls=0;
pushup(x);
}
void modify(int x,int d){
access(x);
splay(x);
v[x]=d;
pushup(x);
}
int getrt(int x){
access(x);
splay(x);
while(ls)x=ls;
return x;
}
int query(int x){
int f=c[x];
splay(x=getrt(x));
return f==c[x]?mx[x]:mx[rs];
}
}t[2];
int h[100010],nex[200010],to[200010],fa[100010],M;
void add(int a,int b){
M++;
to[M]=b;
nex[M]=h[a];
h[a]=M;
}
void dfs(int x){
for(int i=h[x];i;i=nex[i]){
if(to[i]!=fa[x]){
fa[to[i]]=x;
t[c[to[i]]].fa[to[i]]=x;
dfs(to[i]);
t[c[to[i]]].ms[x].insert(t[c[to[i]]].mx[to[i]]);
}
}
t[0].pushup(x);
t[1].pushup(x);
}
int main(){
int n,m,i,x,y;
scanf("%d",&n);
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(i=1;i<=n;i++)scanf("%d",c+i);
for(i=1;i<=n;i++){
scanf("%d",&x);
t[0].v[i]=t[1].v[i]=x;
}
dfs(1);
scanf("%d",&m);
while(m--){
scanf("%d%d",&i,&x);
if(i==0)printf("%d\n",t[c[x]].query(x));
if(i==1){
if(fa[x])t[c[x]].cut(x);
c[x]^=1;
if(fa[x])t[c[x]].link(fa[x],x);
}
if(i==2){
scanf("%d",&y);
t[0].modify(x,y);
t[1].modify(x,y);
}
}
}