DOJ logoDOJ
题目
最近添加的题目收藏的题目Workbooks
分类DLC比赛小组团队讨论区
排名
解题数量排行榜连续解题排名DOJ Power 排行榜
评测状态
征题登录注册
DOJ logoDOJ

支持 OI 子任务计分、Elo 等级分和 Discord 认证的社区在线评测系统。

题目
题目列表分类
社区
比赛排名讨论区公告举办外部比赛指南
账号
登录注册评测状态
政策
服务条款DLC 使用规则隐私政策API 文档语言运行环境比赛排名奖励评级与表现
© 2026 DOJ
保留所有权利
题解

Colorful Ancestors

返回题目

题解

정답을 색별로 나누어 생각하자.

고정된 색 ccc에 대해, 모든 정점 vvv는 Tc(v)T_c(v)Tc​(v)라는 값을 가진다. 이 값은 000이거나 색이 ccc인 어떤 정점이다. 색 ccc가 전체 답에 기여하는 값은 같은 TcT_cTc​ 값을 가지는 순서쌍의 개수이므로,

∑xcntc(x)2\sum_x cnt_c(x)^2x∑​cntc​(x)2

이다. 여기서 cntc(x)cnt_c(x)cntc​(x)는 Tc(v)=xT_c(v)=xTc​(v)=x인 정점 의 개수이다. 는 또는 색이 인 정점이다.

이제 각 색에 대해 이 값을 빠르게 계산하면 된다.

색이 ccc인 정점 xxx를 보자. Tc(v)=xT_c(v)=xTc​(v)=x인 정점 vvv는 다음 조건을 만족한다.

  • vvv는 xxx의 서브트리 안에 있다.
  • xxx에서 vvv로 내려가는 경로에서 xxx를 제외하고 색이 ccc인 정점이 없다.

즉, 처음에는 xxx의 서브트리 크기만큼 후보가 있고, 그중 xxx 바로 아래의 같은 색 정점들이 담당하는 서브트리를 빼면 된다.

여기서 ``바로 아래의 같은 색 정점''이란, 색이 ccc인 정점 yyy 중 xxx가 yyy의 가장 가까운 색 ccc 조상인 정점을 뜻한다.

따라서

cntc(x)=subtree(x)−∑subtree(y)cnt_c(x)=subtree(x)-\sum subtree(y)cntc​(x)=subtree(x)−∑s

이다. 합은 xxx가 가장 가까운 같은 색 조상인 정점 yyy들에 대해 취한다.

남은 것은 각 정점 yyy에 대해 가장 가까운 같은 색 조상 sameParent(y)sameParent(y)sameParent(y)를 구하는 것이다. 이는 루트에서 DFS를 하면서 현재 경로 위에서 각 색의 가장 낮은 정점을 저장하면 된다.

DFS로 정점 vvv에 들어갈 때, 현재 last[Cv]last[C_v]last[Cv​]가 vvv의 가장 가까운 같은 색 조상이다. 그 값을 sameParent(v)sameParent(v)에 저장하고, 로 바꾼다. DFS에서 를 빠져나올 때는 원래 값으로 롤백한다. 각 정점마다 한 번씩만 처리하므로 선형 시간이다.

색 ccc에 대해 Tc(v)=0T_c(v)=0Tc​(v)=0인 정점 수도 필요하다. 색 ccc인 정점 중, 같은 색 조상이 없는 정점들을 생각하자. 이 정점들의 서브트리는 서로 겹치지 않고, 그 안에 있는 정점들은 색 ccc 조상을 하나 이상 가진다. 따라서

cntc(0)=N−∑subtree(x)cnt_c(0)=N-\sum subtree(x)cntc​(0)=N−∑subtree(x)

이다. 합은 같은 색 조상이 없는 색 ccc 정점 xxx들에 대해 취한다.

구현에서는 다음 값을 모은다.

  • sameParent(v)=0sameParent(v)=0sameParent(v)=0이면 rootSum[Cv]rootSum[C_v]rootSum[C에 를 더한다.

그 후 정답은

∑c=1K(N−rootSum[c])2+∑v=1N(subtree(v)−sameChildSum[v])2\sum_{c=1}^{K}(N-rootSum[c])^2+ \sum_{v=1}^{N}(subtree(v)-sameChildSum[v])^2c=1∑K​(N

이다.

DFS는 재귀로 구현하면 N=2 000 000N=2\,000\,000N=2000000에서 스택 오버플로가 날 수 있으므로, 반복문 기반 DFS를 사용하는 것이 안전하다.

시간 복잡도는 O(N)O(N)O(N), 메모리 복잡도는 O(N+K)O(N+K)O(N+K)이다.

vvv
xxx
000
ccc
u
b
t
r
ee
(
y
)
sameParent(v)
last[Cv]=vlast[C_v]=vlast[Cv​]=v
vvv
v
​
]
subtree(v)subtree(v)subtree(v)
  • sameParent(v)≠0sameParent(v)\ne 0sameParent(v)=0이면 sameChildSum[sameParent(v)]sameChildSum[sameParent(v)]sameChildSum[sameParent(v)]에 subtree(v)subtree(v)subtree(v)를 더한다.
  • −
    rootSum[c])2+
    v=1∑N​(subtree(v)−
    sameChildSum[v])2