PS 일지 (2024.03.24)

Bard·2024년 3월 24일
1

PS 일지

목록 보기
11/11
post-thumbnail

B. 트리와 XOR

내가 트리에 좀 약하다는 걸 알고 있기 때문에 도전해봤다.

문제는 어떤 트리가 주어진다. 각각의 노드 viv_i에는 정수 aia_i가 적혀있다.
모든 aia_i를 같게 만들어야 한다.

이때 한 점에 대해서 연산 [vi,c][v_i,c]를 시행하면 viv_i를 루트로 하는 서브트리에 대한 모든 정점 jj에 대해 aja_jajca_j \oplus c로 변경한다. \oplus는 bitwise XOR을 의미한다.

이때의 비용은 scs\cdot c이다.

rr번 정점이 트리의 루트일 때 목표를 달성하기 위한 최소 비용을 mrm_{r}이라 할 때, m1,m2,,mnm_{1}, m_{2}, \ldots, m_{n}을 구하는 문제이다.

풀이에 앞서

  • 정수 AABB가 있을 때, BcB\oplus cAA가 되게 하는 ccABA\oplus B이다.
  • AABB가 서로 다른 정수라면 AcA\oplus cBcB\oplus c또한 서로 다른 정수이다.
  • 그리고 그 둘을 bitwise XOR한 값은 동일하다. (Ac)(Bc)(A\oplus c)\oplus(B\oplus c)는 결합법칙과 교환법칙에 의해 ABA\oplus B이기 때문이다.

풀이 과정

결국 문제가 모든 aia_i를 같게 만들어야 하므로, 우리는 정점 간에 다음 값을 구해야만 한다.

루트 노드의 번호를 rr라고 하고, ii번째 정점의 부모를 p(i)p(i)라고 할 때 다음과 같다.

mr=irsi(aiap(i))m_r = \sum_{i \neq r} s_i \cdot (a_i \oplus a_{p(i)})

어차피 본인보다 상위 정점에서 연산을 해봤자 (aiap(i))(a_i \oplus a_{p(i)}) 값 자체는 변하지 않기 때문이다.

그럼 이 문제는 결국 sis_i를 잘 구하면 되는 문제로 변형된다.

일단 루트 노드 vrv_r에서 mrm_r을 구했다고 가정하자.

이때, vrv_r의 자식 중 하나를 vsv_s라고 하면, msm_s를 구할 때 변하는 건 트리의 크기뿐이다.

vsv_s를 루트노드라고 하면, 원래 vsv_s를 루트로 하는 서브트리의 크기(sss_s)를 변경된 트리에서 vrv_r을 루트로 하는 서브트리의 크기(srs_r)로 바꿔주기만 하면 된다.

그럼 다음 식으로 msm_s를 구할 수 있다.

ms=mr+(asar)(srss)m_s = m_r + (a_s \oplus a_r) \cdot (s_r - s_s)

srs_rsss_s는 한 개의 간선으로 나뉘어지는 노드의 개수이다. 따라서, 이는 각 간선마다 미리 구해둘 수 있다. (O(N)O(N))

profile
The Wandering Caretaker

0개의 댓글