原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3639
Query on a tree VII
Description
You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are numbered from 1 to n.
Each node has a color, white or black, and a weight.
We will ask you to perfrom some instructions of the following form:
0 u : ask for the maximum weight among the nodes which are connected to u, two nodes are connected iff all the node on the path from u to v (inclusive u and v) have a same color.
1 u : toggle the color of u(that is, from black to white, or from white to black).
2 u w: change the weight of u to w.
Input
The first line contains a number n denoted how many nodes in the tree(1 ≤ n ≤ 105). The next n - 1 lines, each line has two numbers (u, v) describe a edge of the tree(1 ≤ u, v ≤ n).
The next 2 lines, each line contains n number, the first line is the initial color of each node(0 or 1), and the second line is the initial weight, let’s say Wi, of each node(|Wi| ≤ 109).
The next line contains a number m denoted how many operations we are going to process(1 ≤ m ≤ 105). The next m lines, each line describe a operation (t, u) as we mentioned above(0 ≤ t ≤ 2, 1 ≤ u ≤ n, |w| ≤ 109).
Output
For each query operation, output the corresponding result.
Sample Input
5
1 2
1 3
1 4
1 5
0 1 1 1 1
1 2 3 4 5
3
0 1
1 1
0 1
Sample Output
1
5
题目大意
询问同色联通块内的最大值,支持修改颜色,修改权值。
题解
前置知识:维护联通块。
Q t r e e \mathcal{Qtree} Qtree系列,板子题一家。
维护联通块的方法见上面链接,剩下的就是维护一个子树的最大值了。此时,如果仅仅维护左右儿子的最大值,显然是不行的, S p l a y \mathcal{Splay} Splay时也没法继续维护。所以,我们需要给每个节点开一个 m u l t i s e t \mathcal{multiset} multiset,将所有虚子树的最大值都丢进去,就可以做到 O ( l o g 2 n ) O(log_2n) O(log2n)更新了。
其他维护大同小异。
借此学习一波 S T L \mathcal{STL} STL姿势。
代码
#include<bits/stdc++.h>
#define ls son[v][0]
#define rs son[v][1]
#define inf INT_MAX
#define C lct[col[a]]
using namespace std;
const int M=1e5+5,N=M<<1;
int col[M],fa[M],val[M],n,m;
vector<int>mmp[M];
struct LCT{
int son[N][2],dad[N],mx[N];
multiset<int>s[N];
LCT(){mx[0]=-inf;}
bool notroot(int v){return son[dad[v]][0]==v||son[dad[v]][1]==v;}
void up(int v){mx[v]=max(val[v],max(mx[ls],mx[rs]));if(!s[v].empty())mx[v]=max(mx[v],*s[v].rbegin());}
void spin(int v)
{
int f=dad[v],ff=dad[f],k=son[f][1]==v,w=son[v][!k];
if(notroot(f))son[ff][son[ff][1]==f]=v;son[v][!k]=f;son[f][k]=w;
if(w)dad[w]=f;dad[f]=v;dad[v]=ff;up(f);
}
void splay(int v)
{
int f,ff;
while(notroot(v))
{
f=dad[v];ff=dad[f];
if(notroot(f))spin((son[f][0]==v)^(son[ff][0]==f)?v:f);
spin(v);
}
up(v);
}
void access(int v)
{for(int f=0;v;v=dad[f=v]){splay(v);if(rs)s[v].insert(mx[rs]);if(rs=f)s[v].erase(s[v].find(mx[f]));up(v);}}
int root(int v){access(v);splay(v);while(ls)v=ls;splay(v);return v;}
void link(int v){splay(v);int f=dad[v]=fa[v];access(f);splay(f);son[f][1]=v;up(f);}
void cut(int v){access(v);splay(v);ls=dad[ls]=0;up(v);}
}lct[2];
void dfs(int v,int f)
{
fa[v]=f;int to;
for(int i=mmp[v].size()-1;i>=0;--i)
{to=mmp[v][i];if(to==f)continue;dfs(to,v);}
lct[col[v]].link(v);
}
void in()
{
int a,b;scanf("%d",&n);
for(int i=1;i<n;++i)scanf("%d%d",&a,&b),mmp[a].push_back(b),mmp[b].push_back(a);
for(int i=1;i<=n;++i)scanf("%d",&col[i]);
for(int i=1;i<=n;++i)scanf("%d",&val[i]);
}
void ac()
{
int op,a;dfs(1,n+1);scanf("%d",&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d",&op,&a);
switch(op)
{
case 0:printf("%d\n",C.mx[C.son[C.root(a)][1]]);break;
case 1:C.cut(a);col[a]^=1;C.link(a);break;
case 2:C.access(a);C.splay(a);scanf("%d",&val[a]);C.up(a);
}
}
}
int main(){in();ac();}