Blog of RuSun

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

P4074 [WC2013] 糖果公园

P4074 [WC2013] 糖果公园

将树拍成一个括号序,那么问题转化为了序列上的带修改的莫队问题。还有一些细节问题,注意到两点的 $lca$ 不一定会被计算,那么单独记录一下 $lca$ 。如果只记录进入序列的位置的话,第一个点会被抵消掉,处理方法是将询问位置 +1 即可。

查看代码
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <cstdio>
#include <vector>
#include <algorithm>
#define pb push_back
typedef long long L;
using namespace std;
const int B = 3420;
const int N = 1e5 + 10, M = 2e5 + 10, K = 18;
vector <int> e[N];
L cur, ans[N];
bool vis[N];
int idx, dfn[M], f[N];
int n, m, q, blk[M], V[N], W[N], C[N], cnt[N];
struct Query
{
int l, r, a, t, id;
Query (int _l, int _r, int _a, int _t, int _id) :
l(_l), r(_r), a(_a), t(_t), id(_id) { }
bool operator < (const Query &_) const
{
if (blk[l] ^ blk[_.l])
return blk[l] < blk[_.l];
if (blk[r] ^ blk[_.r])
return blk[r] < blk[_.r];
return t < _.t;
}
};
vector <Query> qs;
struct Modifiy
{
int x, a, b;
Modifiy (int _x, int _a, int _b) : x(_x), a(_a), b(_b) { }
};
vector <Modifiy> ms;
namespace LCA
{
int stmp, d[N], id[N], st[M][K], lg[M];
void dfs(int u = 1, int fa = 0)
{
st[++stmp][0] = u;
d[u] = d[fa] + 1;
id[u] = stmp;
for (int v : e[u]) if (v ^ fa)
{
dfs(v, u);
st[++stmp][0] = u;
}
}
int dmin(int x, int y)
{ return d[x] < d[y] ? x : y; }
void init()
{
dfs();
for (int i = 2; i <= stmp; i++)
lg[i] = lg[i >> 1] + 1;
for (int k = 1; (1 << k) <= stmp; k++)
for (int i = 1; i + (1 << k) - 1 <= stmp; i++)
st[i][k] = dmin(st[i][k - 1], st[i + (1 << k - 1)][k - 1]);
}
int lca(int x, int y)
{
x = id[x], y = id[y];
if (x > y) swap(x, y);
int k = lg[y - x + 1];
return dmin(st[x][k], st[y - (1 << k) + 1][k]);
}
}
void add (int x)
{
if (!vis[x])
cur += (L)V[C[x]] * W[++cnt[C[x]]];
else
cur -= (L)V[C[x]] * W[cnt[C[x]]--];
vis[x] ^= 1;
}
void change (int x, int c)
{
if (vis[x])
add(x), C[x] = c, add(x);
else C[x] = c;
}
void dfs (int u = 1, int fa = 0)
{
dfn[f[u] = ++idx] = u;
for (int v : e[u]) if (v ^ fa)
dfs(v, u);
dfn[++idx] = u;
}
int main ()
{
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= m; ++i) scanf("%d", &V[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &W[i]);
for (int i = 1, a, b; i < n; ++i)
{
scanf("%d%d", &a, &b);
e[a].pb(b), e[b].pb(a);
}
for (int i = 1; i <= n; ++i) scanf("%d", &C[i]);
LCA::init();
dfs();
for (int i = 1; i <= idx; ++i)
blk[i] = i / B;
for (int op; q; --q)
{
scanf("%d", &op);
if (op == 0)
{
int x, c; scanf("%d%d", &x, &c);
ms.pb(Modifiy(x, C[x], c)), C[x] = c;
}
else if (op == 1)
{
int u, v; scanf("%d%d", &u, &v);
int t = LCA::lca(u, v);
if (u == t)
qs.pb(Query(f[u] + 1, f[v], u, ms.size(), qs.size()));
else if (v == t)
qs.pb(Query(f[v] + 1, f[u], v, ms.size(), qs.size()));
else
{
u = f[u], v = f[v];
if (u > v) swap(u, v);
qs.pb(Query(u + 1, v, t, ms.size(), qs.size()));
}
}
}
sort(qs.begin(), qs.end());
int l = 1, r = 0, t = ms.size();
for (Query i : qs)
{
while (t < i.t)
change(ms[t].x, ms[t].b), ++t;
while (t > i.t)
--t, change(ms[t].x, ms[t].a);
while (l > i.l) add(dfn[--l]);
while (l < i.l) add(dfn[l++]);
while (r < i.r) add(dfn[++r]);
while (r > i.r) add(dfn[r--]);
add(i.a);
ans[i.id] = cur;
add(i.a);
}
for (int i = 0; i < qs.size(); ++i)
printf("%lld\n", ans[i]);
return 0;
}