Blog of RuSun

\begin {array}{c} \mathfrak {One Problem Is Difficult} \\\\ \mathfrak {Because You Don't Know} \\\\ \mathfrak {Why It Is Diffucult} \end {array}

P6018 [Ynoi2010] Fusion tree

P6018 [Ynoi2010] Fusion tree

与一个节点距离 $1$ 的节点包括其父亲,其儿子,那么,对于操作 $1$ ,将父亲加 $1$ ,将该点打一个标记,表示其儿子的值需要加 $1$ 。

查询时,需要所有儿子的信息,考虑如何维护。对于每一个点建立一棵 trie ,将所有儿子插入,可以维护出整课数的异或和,考虑整棵树加 $1$ ,对于一个树,相当于清除末尾的 $1$ ,将上一位的 $0$ 改为 $1$ ,具体地,在 Trie 上,每次交换两个儿子,并进入 $0$ 继续递归。

这样可以实现 $O(\log ^ 2 w)$ 整体加任意数。

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <cstdio>
#include <vector>
using namespace std;
template <class Type>
void read(Type &x)
{
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9')
c == '-' && (flag = true);
x = c - '0';
while ((c = getchar()) >= '0' && c <= '9')
x = (x << 3) + (x << 1) + c - '0';
if (flag) x = ~x + 1;
}
template <class Type, class ...rest>
void read(Type &x, rest &...y) { read(x), read(y...); }
template <class Type>
void write(Type x)
{
if (x < 0) putchar('-'), x = ~x + 1;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
const int N = 5e5 + 10, M = 1e7 + 10, K = 20;
int n, m, p[N], w[N], v[N], rt[N];
int idx;
struct Node
{
bool sz;
int s[2], v;
} tr[M];
vector <int> g[N];
void dfs (int x)
{
for (int i : g[x]) if (i ^ p[x])
p[i] = x, dfs(i);
}
void pushup (int x)
{
tr[x].sz = tr[tr[x].s[0]].sz ^ tr[tr[x].s[1]].sz;
tr[x].v = (tr[tr[x].s[0]].v ^ tr[tr[x].s[1]].v) << 1 | tr[tr[x].s[1]].sz;
}
void pushdown (int x)
{
if (!x) return;
swap(tr[x].s[0], tr[x].s[1]);
pushdown(tr[x].s[0]);
pushup(x);
}
void modify (int &x, int k, bool op, int d = 0)
{
if (!x)
if (op) x = ++idx;
else return;
if (d == K) return void(tr[x].sz ^= 1);
modify(tr[x].s[k >> d & 1], k, op, d + 1);
pushup(x);
}
int calc (int x)
{
return v[p[x]] + w[x];
}
void add (int x, int k)
{
if (p[x]) modify(rt[p[x]], calc(x), 0);
w[x] += k;
if (p[x]) modify(rt[p[x]], calc(x), 1);
}
int main ()
{
read(n, m);
for (int i = 1, a, b; i < n; ++i)
{
read(a, b);
g[a].push_back(b), g[b].push_back(a);
}
dfs(1);
for (int i = 1; i <= n; ++i)
{
read(w[i]);
if (p[i]) modify(rt[p[i]], w[i], 1);
}
for (int op; m; --m)
{
read(op);
if (op == 1)
{
int x;
read(x);
if (p[x]) add(p[x], 1);
++v[x];
pushdown(rt[x]);
}
else if (op == 2)
{
int x, v;
read(x, v);
add(x, -v);
}
else if (op == 3)
{
int x;
read(x);
write(tr[rt[x]].v ^ calc(p[x])), puts("");
}
}
return 0;
}