洛谷传送门
题目描述
You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are numbered from 1 1 to . Each node has a color, white or black, and a weight. We will ask you to perfrom some instructions of the following form:
0
0
: ask for the maximum weight among the nodes which are connected to u, two nodes are connected if all the node on the path from
u
u
to (inclusive
u
u
and ) have a same color.
1
1
: toggle the color of
u
u
(that is, from black to white, or from white to black).
u
u
: change the weight of
u
u
to .
输入输出格式
输入格式:
The first line contains a number n denoted how many nodes in the tree (1≤n≤105) ( 1 ≤ n ≤ 10 5 ) . The next n−1 n − 1 lines, each line has two numbers (u,v) ( u , v ) describe a edge of the tree (1≤u,v≤n) ( 1 ≤ u , v ≤ n ) . The next 2 2 lines, each line contains number, the first line is the initial color of each node (0 or 1) ( 0 o r 1 ) , and the second line is the initial weight, let’s say Wi W i , of each node (|Wi|≤109) ( | W i | ≤ 10 9 ) . The next line contains a number m denoted how many operations we are going to process (1≤m≤105) ( 1 ≤ m ≤ 10 5 ) . The next m lines, each line describe a operation (t,u) ( t , u ) as we mentioned above (0≤t≤2,1≤u≤n,|w|≤109) ( 0 ≤ t ≤ 2 , 1 ≤ u ≤ n , | w | ≤ 10 9 ) .
输出格式:
For each query operation, output the corresponding result.
输入输出样例
输入样例#1:
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
1 2
输出样例#1:
1
5
输入样例#2:
7
1 2
1 3
2 4
2 5
3 6
3 7
0 0 0 0 0 0 0
1 2 3 4 5 6 7
4
0 1
1 1
0 2
0 3
输出样例#2:
7
5
7
解题分析
和 Qtree6 Q t r e e 6 一样, 我们可以建立黑白两棵树, 连通块的最大值我们用一个 multiset m u l t i s e t 维护, 每次在 access a c c e s s 的时候插入/删除信息即可。
不过multiset很坑的一点是如果 erase e r a s e 一个值的话会将所有那个值 erase e r a s e 掉, 所以需要先 find f i n d 到指针。博主莫名其妙WA了很多次…
代码如下:
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <set>
#include <limits.h>
#define R register
#define IN inline
#define gc getchar()
#define W while
#define MX 100010
#define dad tree[typ][now].fat
#define ls tree[typ][now].son[0]
#define rs tree[typ][now].son[1]
bool fu;
template <class T>
IN void in (T &x)
{
fu = false; x = 0; R char c = gc;
W (!isdigit(c))
{ if(c == '-') fu = true; c = gc;}
W (isdigit(c))
x = (x << 1) + (x << 3) + c - 48, c = gc;
if(fu) x = -x;
}
namespace LCT
{
int fat[MX], dot, q, cnt, head[MX], col[MX];
struct Edge
{
int to, nex;
}edge[MX << 1];
IN void addedge(const int &from, const int &to)
{edge[++cnt] = {to, head[from]}, head[from] = cnt;}
struct Node
{
int son[2], fat, val, mx;
std::multiset <int> vir;
}tree[2][MX];
IN bool get(const int &typ, const int &now) {return tree[typ][dad].son[1] == now;}
IN bool nroot(const int &typ, const int &now) {return tree[typ][dad].son[1] == now || tree[typ][dad].son[0] == now;}
IN void pushup(const int &typ, const int &now)
{
tree[typ][now].mx = std::max(tree[typ][ls].mx, std::max(tree[typ][now].val, tree[typ][rs].mx));
if(!tree[typ][now].vir.empty()) tree[typ][now].mx = std::max(tree[typ][now].mx, *tree[typ][now].vir.rbegin());//注意rbegin和end的区别
}
IN void rotate(const int &typ, const int &now)
{
R bool dir = get(typ, now);
R int fa = dad, grand = tree[typ][fa].fat;
tree[typ][fa].son[dir] = tree[typ][now].son[dir ^ 1];
tree[typ][tree[typ][now].son[dir ^ 1]].fat = fa;
if(nroot(typ, fa)) tree[typ][grand].son[get(typ, fa)] = now;
tree[typ][now].fat = grand;
tree[typ][now].son[dir ^ 1] = fa;
tree[typ][fa].fat = now;
pushup(typ, fa);
}
IN void splay(const int &typ, R int now)
{
R int fa, grand;
W (nroot(typ, now))
{
fa = dad, grand = tree[typ][fa].fat;
if(nroot(typ, fa)) rotate(typ, (get(typ, now) == get(typ, fa) ? fa : now));
rotate(typ, now);
}
pushup(typ, now);
}
IN void access(const int &typ, R int now)
{
for (R int x = 0; now; x = now, now = dad)
{
splay(typ, now);
if(rs) tree[typ][now].vir.insert(tree[typ][rs].mx);
if(x) tree[typ][now].vir.erase(tree[typ][now].vir.find(tree[typ][x].mx));
rs = x; pushup(typ, now);
}
}
IN int findroot(const int &typ, R int now)
{
access(typ, now), splay(typ, now);
W (ls) now = ls;
splay(typ, now);
return now;
}
IN void link(const int &typ, const int &now)
{
splay(typ, now);
R int fa = dad = fat[now];
access(typ, fa), splay(typ, fa);
tree[typ][fa].son[1] = now; pushup(typ, fa);
}
IN void cut (const int &typ, const int &now)
{
access(typ, now), splay(typ, now);
ls = tree[typ][ls].fat = 0;
pushup(typ, now);
}
void DFS(const int &now)
{
for (R int i = head[now]; i; i = edge[i].nex)
{
if(edge[i].to == fat[now]) continue;
fat[edge[i].to] = now;
DFS(edge[i].to);
}
link(col[now], now);
}
IN void modify(const int &typ, const int &now, const int &del)
{
access(typ, now), splay(typ, now);
tree[typ][now].val = del;
pushup(typ, now);
}
}
using namespace LCT;
int main(void)
{
int a, b, c, rt;
in(dot);
for (R int i = 1; i < dot; ++i)
in(a), in(b), addedge(a, b), addedge(b, a);
for (R int i = 1; i <= dot; ++i) in(col[i]);
for (R int i = 0; i <= dot; ++i) tree[0][i].mx = tree[1][i].mx = -INT_MAX;//有负数, 所以要足够小
for (R int i = 1; i <= dot; ++i) in(tree[col[i]][i].val), tree[col[i] ^ 1][i].val = tree[col[i]][i].val;//初始化时两棵树都要保存
fat[1] = dot + 1; tree[0][dot + 1].mx = tree[1][dot + 1].mx = -INT_MAX;
DFS(1);
in(q);
W (q--)
{
in(a), in(b);
switch (a)
{
case 0:
{
rt = findroot(col[b], b);
printf("%d\n", tree[col[b]][tree[col[b]][rt].son[1]].mx);
break;
}
case 1:
{
cut(col[b], b);
col[b] ^= 1;
link(col[b], b);
break;
}
case 2:
{
in(c);
modify(col[b], b, c);
modify(col[b] ^ 1, b, c);
break;
}
}
}
}