เศรษฐีแบ่งสมบัติ

o61_may08_estate

ให้ mm คือจำนวนบ้านที่เศรษฐีมีในตอนนี้ แน่นอนว่าถ้า kmk \nmid m คำตอบจะเป็น NO เสมอ ดังนั้นเราจึงเหลือแค่กรณีที่ kmk \mid m

พิจารณาต้นไม้ TT ของเราในปัจจุบันที่มีขนาด mm เราจะทำการ root TT ที่ node หมายเลข 1 จากนั้นนิยาม S(u)S(u) เป็นจำนวน node ใน subtree ของ uu (รวม uu ด้วย) ข้อสังเกตสำคัญในการแก้โจทย์ข้อนี้คือ "เศรษฐีจะสามารถแบ่งสมบัติตามที่โจทย์ต้องการก็ต่อเมื่อมีจุดยอด uu ที่ kS(u)k|S(u) จำนวน m/km/k จุดพอดี"

ปัญหาของเราจึงกลายเป็นการเก็บและอัพเดทค่า S(u)S(u) หลังจากบ้านแต่ละหลังถูกสร้างขึ้น หากเราแก้ปัญหานี้ตรง ๆ จะใช้เวลา O(n2)\mathcal{O}(n^2) ซึ่งจะไม่ทันเวลา

เพื่อที่จะ optimize อัลกอริธึมของเรา เราจะสร้าง tree ต้นเต็มเก็บไว้ก่อน จากนั้นในแต่ละจุดยอด uu เราจะมีอาเรย์ 1 มิติขนาด kk โดยเราจะเรียกอาเรย์นี้ว่า T(u)T(u) โดยที่ T(u)[i]T(u)[i] จะเก็บ จำนวนจุดยอด vv ใน subtree ของ uu (รวม uu ด้วย) ที่ S(v)modk=iS(v) \bmod k = i

ในการเก็บและอัพเดทค่า T(u)T(u) ให้เราสังเกตว่าในการสร้างบ้านใหม่แต่ละครั้ง จุดยอดที่มีค่า TT เปลี่ยนแปลงไปจะเป็นจุดยอดบน path จากจุดยอดหมายเลข 1 ถึงจุดยอดหมายเลข uu เท่านั้น ปัญหานี้จึงกลายเป็นปัญหา range update บน tree ซึ่งสามารถทำได้ใน O(logn)\mathcal{O}(\log n) โดย Heavy-Light Decomposition

เราจะตอบ YES ก็ต่อเมื่อ T(1)[0]=m/kT(1)[0] = m/k

ในการอัพเดทใน segment tree ใน Heavy-Light Decomposition จะใช้เวลา O(k)\mathcal{O}(k) ไปด้วย ทำให้เราสามารถแก้โจทย์ข้อนี้ในเวลา O(nklogn)\mathcal{O}(nk\log n)