import
java.util.ArrayList;
import
java.util.Collections;
import
java.util.List;
public
class
Main {
private
static
final
int
maxColor =
1000005
;
private
static
final
int
maxn =
100005
;
private
static
int
[] bit =
new
int
[maxn];
private
static
int
[] visTime =
new
int
[maxn];
private
static
int
[] endTime =
new
int
[maxn];
private
static
int
[] flatTree =
new
int
[
2
* maxn];
private
static
List<Integer>[] tree =
new
ArrayList[maxn];
private
static
List<Integer>[] table =
new
ArrayList[maxColor];
private
static
int
[] traverser =
new
int
[maxColor];
private
static
boolean
[] vis =
new
boolean
[maxn];
private
static
int
tim =
0
;
private
static
List<Pair<Pair<Integer, Integer>, Integer>> queries =
new
ArrayList<>();
private
static
int
[] ans =
new
int
[maxn];
private
static
void
update(
int
idx,
int
val) {
while
(idx < maxn) {
bit[idx] += val;
idx += idx & -idx;
}
}
private
static
int
query(
int
idx) {
int
res =
0
;
while
(idx >
0
) {
res += bit[idx];
idx -= idx & -idx;
}
return
res;
}
private
static
void
dfs(
int
v,
int
[] color) {
vis[v] =
true
;
visTime[v] = ++tim;
flatTree[tim] = color[v];
for
(
int
u : tree[v]) {
if
(!vis[u]) {
dfs(u, color);
}
}
endTime[v] = ++tim;
flatTree[tim] = color[v];
}
private
static
void
addEdge(
int
u,
int
v) {
tree[u].add(v);
tree[v].add(u);
}
private
static
void
hashMarkFirstOccurrences(
int
n) {
for
(
int
i =
1
; i <=
2
* n; i++) {
table[flatTree[i]].add(i);
if
(table[flatTree[i]].size() ==
1
) {
update(i,
1
);
traverser[flatTree[i]]++;
}
}
}
private
static
void
processQueries() {
int
j =
1
;
for
(Pair<Pair<Integer, Integer>, Integer> query : queries) {
for
(; j < query.first.first; j++) {
int
elem = flatTree[j];
update(table[elem].get(traverser[elem] -
1
), -
1
);
if
(traverser[elem] < table[elem].size()) {
update(table[elem].get(traverser[elem]),
1
);
traverser[elem]++;
}
}
ans[query.second] = query(query.first.second);
}
}
private
static
void
countDistinctColors(
int
[] color,
int
n,
int
[] qVer,
int
qn) {
dfs(
1
, color);
for
(
int
i =
0
; i < qn; i++) {
queries.add(
new
Pair<>(
new
Pair<>(visTime[qVer[i]], endTime[qVer[i]]), i));
}
Collections.sort(queries);
hashMarkFirstOccurrences(n);
processQueries();
for
(
int
i =
0
; i < queries.size(); i++) {
System.out.println(
"Distinct colors in the corresponding subtree is: "
+ ans[i]);
}
}
public
static
void
main(String[] args) {
int
n =
11
;
int
[] color = {
0
,
2
,
3
,
3
,
4
,
1
,
3
,
4
,
3
,
2
,
1
,
1
};
for
(
int
i =
0
; i < maxn; i++) {
tree[i] =
new
ArrayList<>();
table[i] =
new
ArrayList<>();
}
addEdge(
1
,
2
);
addEdge(
1
,
3
);
addEdge(
2
,
4
);
addEdge(
2
,
5
);
addEdge(
2
,
6
);
addEdge(
3
,
7
);
addEdge(
3
,
8
);
addEdge(
7
,
9
);
addEdge(
7
,
10
);
addEdge(
7
,
11
);
int
[] qVer = {
3
,
2
,
7
};
int
qn = qVer.length;
countDistinctColors(color, n, qVer, qn);
}
static
class
Pair<A, B>
implements
Comparable<Pair<A, B>> {
A first;
B second;
public
Pair(A first, B second) {
this
.first = first;
this
.second = second;
}
@Override
public
int
compareTo(Pair<A, B> other) {
if
(
this
.first.equals(other.first)) {
return
((Comparable<B>)
this
.second).compareTo(other.second);
}
else
{
return
((Comparable<A>)
this
.first).compareTo(other.first);
}
}
}
}