BZOJ3639 Query on a tree VII

原题链接: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();}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值