LCA
λ Least Common Ancestor
μ μ½μμ΄λ€. Tree
μμμ κ³΅ν΅ μ‘°μ
μ μ°Ύλ λ¬Έμ μ μ¬μ©λλ μκ³ λ¦¬μ¦μ΄λ€. κ³΅ν΅ μ‘°μμ΄ μ¬λ¬κ° μμ μ μμΌλ―λ‘, κ·Έ μ€μ μ μΌ λΉ λ₯Έ μ‘°μμ LCA
λ‘ μ μνλ€. input
μΌλ‘λ μλ‘ λ€λ₯Έ λ Node
κ° μ£Όμ΄μ§λ€. μ΄ λ Node
λ₯Ό l
κ³Ό r
μ΄λΌ νμ.
λ§μ½ Node
μ depth
λ₯Ό λͺ¨λ₯Έλ€λ©΄ μ΄ λ°©λ²λ°μ μ¬μ€ μ¬μ©ν μκ° μλ€. κ° lμ λν΄(lμ΄ rootκ° λ λκΉμ§) λͺ¨λ rμ μννλ€. μ½λλ₯Ό 보면 μκ² μ§λ§ 무쑰건 μ°Ύμ μλ°μ μλ€.
for(Node* l = sl; l != 0; l = l->parent) {for(Node* r = sr; r != 0; r = r->parent) {if (l == r) return l;}}
λ§μ½ depth
λ₯Ό μλ€λ©΄, l
κ³Ό r
μ depth
λ₯Ό κ°κ² λ§μΆ μ΄νμ, μμͺ½ Node
λ₯Ό λ§λ λκΉμ§ κ°μ΄ μ¬λ¦¬λ©΄ λλ€. ꡬνμ νΈμλ₯Ό μν΄ μ²μμλ 무쑰건 l
μ depth
κ° ν¬λλ‘ swap
μ νλ κ²μ΄ νΈνλ€. μ΄λ κ² κ΅¬ννλ©΄ 2μ€ν¬λ¬Έμ΄ μκΈ° λλ¬Έμ worst
λ O(n)
μ΄λ€.
if (l->depth < r->depth) swap(l, r);while(l->depth > r->depth) l = l->parent;for(;;l = l->parent, r = r->parent) {if (l == r) return l;}
O(log n)
λ‘ κ΅¬ννλ €λ©΄ μλ 2μ§μμ λμλ°©μμ μ΄ν΄ν νμκ° μλ€.
λΉμ°ν μ리μ§λ§, 2μ§μλ λͺ¨λ 10μ§μλ₯Ό λνλΌ μ μλ€. λ§μ½μ μμμ Node
μ λν΄μ λΆλͺ¨λ₯Ό μ μ νκ² μ μ₯νλ©΄ λΆλͺ¨λ‘ μ¬λΌκ°λ κ³Όμ μ O(n)
μ΄ μλ O(log n)
μΌλ‘ ν μ μλ€. λ°λ‘, λΆλͺ¨λ₯Ό μ μ₯νλλ°, μ 체 λΆλͺ¨λ₯Ό μ μ₯νλ κ²μ΄ μλλΌ, 1
, 2
, 4
, 8
, μ²λΌ 2μ§μμ μ°μ΄λ μ«μμ λΆλͺ¨λ€μ μ μ₯νλ κ²μ΄λ€. μ΄λ κ² μ μ₯νλ©΄, λ§μ½ νΉμ λ
Έλμ 8
λ²μ§Έ λΆλͺ¨λ₯Ό ꡬνλ€κ³ νμ λ, νΉμ λ
Έλμ 4
λ²μ§Έ λΆλͺ¨μ 4
λ²μ§Έ λΆλͺ¨λ₯Ό ꡬνλ μμΌλ‘ μκ°ν μ μκ² λλ€. μ΄λ κ²λ§ μ μ₯ν΄λ, 7
= 0111
(2μ§μλ‘) μ΄κΈ° λλ¬Έμ, λͺ¨λ μμμ μμ°μμ λΆλͺ¨λ₯Ό O(log n)
μκ°μ μ°Ύμ μ μκ² λλ€. μ΄λ₯Ό μ½κ² ꡬννκΈ° μν΄μλ bitmask
λ₯Ό μ¬μ©νλ©΄ λλ€. μμμ μλ§νΌμ λΆλͺ¨λ‘ κ°λ μ½λλ μλμ κ°λ€.
struct Node {Node* parents[10]; // μ΅λ 2^9μ λΆλͺ¨λ₯Ό μ μ₯νλ€.};Node* findParent(Node* cur, int num) {int mask = 0x1;for(int i = 0; i < 10; ++i, mask <<= 1) {if (num & mask) cur = cur->parents[i]; // 2μ μ§μμΉλ§νΌμ λΆλͺ¨λ‘ μ΄λνλ€.}return cur;}
2^k
μ λΆλͺ¨λ₯Ό μ μ₯νλ κ²μ μ½λμ node->parents[k]
λ₯Ό 보λ κ²μΌλ‘ ꡬνμ΄ λλ€. μ΄λ₯Ό νμ©νλ©΄ LCA
λ ꡬνν μ μλ€. μ ν
ν¬λμ νμ©νλ€.
if (l->depth < r->depth) swap(l, r);int diff = l->depth - r->depth;// 1. depthλ₯Ό λ§μΆ°μ€λ€.int mask = 0x1;for(int i = 0; i < 10; ++i, mask <<= 1) {if (num & mask) l = l->parents[i]; // 2μ μ§μμΉλ§νΌμ λΆλͺ¨λ‘ μ΄λνλ€.}if (l == r) return l;// 2. κ°μμ§κΈ° μ§μ κΉμ§ μ¬λΌκ°λ€.for(int i = 10 - 1; i >= 0; --i) {Node* nl = l->parents[i];Node* nr = r->parents[i];if (nl == nr) continue;l = nl; r = nr;}while(l != r) {l = l->parents[0];r = r->parents[0];}return l;
κ·Έλ°λ°, μ€λͺ
μ€μ νκ°μ§ λΉ λ¨λ¦° κ²μ΄ μλ€. parents[]
μ μ΄κΈ°νλ μ΄λ»κ² ν κ²μΈκ°? μ΄λ₯Ό μ½κ² νκΈ° μν΄μλ μλμ κ°μ μμμ νμ©νλ€.
2^k = 2^(k-1) + 2^(k-1)
μ¬μ€ λΉμ°ν μμμΈλ°, μκ°νκΈ΄ μ¬μ€ μ½μ§ μλ€. μ΄ μμμ νμ©ν΄μ parents[]
λ₯Ό μ΄κΈ°ν ν μ μλ€.
for(int i = 0; i < 10; ++i) {if (n->parents[i - 1] != nullptr)n->parents[i] = n->parents[i - 1]->parents[i - 1];else n->parents[i] = nullptr;}
μλ‘μ΄ κ°μ΄ μΆκ°λ λ, μμ κ°μ΄ Node
λ₯Ό μ
λ°μ΄νΈ νλ©΄ λλ€. λ§μ½ Addκ° λ€ λ μνμμ parents[]
λ₯Ό μ±μμΌ νλ€λ©΄, root
λΆν° μμν΄μ μμμΌλ‘ μ±μ°λ©΄ λλ€.