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
148
149
150
151
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
struct SegmentTree {
int n;
vector<int> color; // -1: mixed, >=0: uniform color (0 means uncolored)
vector<int> *cnt; // counts per color (1..C)
vector<int> *freq; // freq[k] = number of colors having exactly k edges
int C;
SegmentTree(int n_, int C_, vector<int> &cntRef, vector<int> &freqRef)
: n(n_), color(4 * n_, 0), cnt(&cntRef), freq(&freqRef), C(C_) {}
inline void apply_set(int idx, int l, int r, int newColor) {
int old = color[idx];
if (old == newColor) return;
int len = r - l + 1;
if (old >= 1) {
int &oldCnt = (*cnt)[old];
(*freq)[oldCnt]--;
oldCnt -= len;
(*freq)[oldCnt]++;
}
{
int &newCnt = (*cnt)[newColor];
(*freq)[newCnt]--;
newCnt += len;
(*freq)[newCnt]++;
}
color[idx] = newColor;
}
inline void push_down(int idx) {
if (color[idx] >= 0) {
color[idx * 2] = color[idx];
color[idx * 2 + 1] = color[idx];
color[idx] = -1;
}
}
inline void pull_up(int idx) {
int lc = color[idx * 2], rc = color[idx * 2 + 1];
if (lc >= 0 && lc == rc) color[idx] = lc;
else color[idx] = -1;
}
void update(int idx, int l, int r, int ql, int qr, int newColor) {
if (qr < l || r < ql) return;
if (ql <= l && r <= qr && color[idx] >= 0) {
if (color[idx] != newColor) apply_set(idx, l, r, newColor);
return;
}
if (l == r) {
if (color[idx] != newColor) apply_set(idx, l, r, newColor);
return;
}
if (color[idx] >= 0) push_down(idx);
int mid = (l + r) >> 1;
update(idx * 2, l, mid, ql, qr, newColor);
update(idx * 2 + 1, mid + 1, r, ql, qr, newColor);
pull_up(idx);
}
void update(int l, int r, int newColor) {
if (l > r) return;
update(1, 1, n, l, r, newColor);
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, C, Q;
if (!(cin >> n >> C >> Q)) return 0;
vector<vector<int>> adj(n + 1);
for (int i = 0; i < n - 1; ++i) {
int u, v; cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
// HLD prep: parent, depth, size, heavy
vector<int> parent(n + 1, 0), depth(n + 1, 0), heavy(n + 1, -1), sz(n + 1, 0);
vector<int> order;
order.reserve(n);
{
// iterative DFS
vector<int> st; st.reserve(n);
st.push_back(1);
parent[1] = 0; depth[1] = 0;
while (!st.empty()) {
int v = st.back(); st.pop_back();
order.push_back(v);
for (int w : adj[v]) if (w != parent[v]) {
if (parent[w] == 0) {
parent[w] = v;
depth[w] = depth[v] + 1;
st.push_back(w);
}
}
}
for (int i = (int)order.size() - 1; i >= 0; --i) {
int v = order[i];
sz[v] = 1;
int bestSize = 0, bestChild = -1;
for (int w : adj[v]) if (w == parent[v]) continue; else {
sz[v] += sz[w];
if (sz[w] > bestSize) { bestSize = sz[w]; bestChild = w; }
}
heavy[v] = bestChild;
}
}
// HLD decompose
vector<int> head(n + 1, 0), pos(n + 1, 0);
int curPos = 1;
for (int v = 1; v <= n; ++v) {
if (parent[v] == 0 || heavy[parent[v]] != v) {
for (int u = v; u != -1; u = heavy[u]) {
head[u] = v;
pos[u] = curPos++;
}
}
}
// pos[1] is root; edges correspond to pos[u] for u != 1
vector<int> cnt(C + 1, 0);
vector<int> freq(n, 0); // 0..n-1
freq[0] = C;
SegmentTree stree(n, C, cnt, freq);
auto update_path_to_root = [&](int u, int color) {
while (head[u] != head[1]) {
int hu = head[u];
stree.update(pos[hu], pos[u], color);
u = parent[hu];
}
if (pos[1] + 1 <= pos[u]) stree.update(pos[1] + 1, pos[u], color);
};
for (int i = 0; i < Q; ++i) {
int u, c, m; cin >> u >> c >> m;
update_path_to_root(u, c);
cout << freq[m] << '\n';
}
return 0;
}
|