Jump

1107

หากโจทย์ต้องการให้หาค่ามากสุดหรือน้อยสุดที่ทำให้เงื่อนไขเกี่ยวกับค่ามากสุด/น้อยสุดบางอย่างเป็นจริง เทคนิคหนึ่งที่ควรนึกถึงคือการแปลงปัญหาเป็น Decision Problem แล้วทำการ Binary Search

สมมุติให้ "ค่าของความน่าเบื่อของคาบที่เข้าเรียนที่น่าเบื่อมากที่สุด" ที่ยอมรับได้เป็น aa นั่นคือ โจทย์ต้องการให้เราหาค่า aa ที่สามารถหาวิธีโดดเรียนได้จริง (เรียกว่า amina_{min})

สังเกตว่า

  • หากทดลองให้ a=a0a = a_0 แล้วเราสามารถหาวิธีโดดเรียนได้ จะได้ amina0a_{min} \leq a_0
  • หากทดลองให้ a=a0a = a_0 แล้วหาวิธีโดดเรียนไม่ได้ จะได้ amin>a0a_{min} > a_0

ดังนั้น เราสามารถหา amina_{min} ได้ด้วย Binary Search โดยขอบเขตเริ่มต้นคือ [x,y][x, y] เมื่อ x=x= ค่าที่น้อยสุดในข้อมูลนำเข้า และ y=y= ค่าที่มากที่สุดในข้อมูลนำเข้า

สมมุติว่าโจทย์ไม่มีเงื่อนไขบังคับว่า "ต้องเข้าเรียนอย่างน้อย 1 คาบในแต่ละวัน" การตรวจสอบว่าสามารถหาวิธีโดดเรียนให้ค่าความน่าเบื่อมากสุดไม่เกิน aa ได้จริงหรือไม่ ทำได้ด้วย Greedy Algorithm ดังนี้

  • ดูว่าคาบแรกน่าเบื่อเกิน aa หรือไม่ ถ้าเกิน เราจะโดดคาบที่ 11 ถึง pp แล้วไปพิจารณาคาบที่ p+2p+2 ต่อเลย แต่จะเหลือสิทธิ์โดดเรียนเพียง k1k-1 ครั้ง
  • ถ้าคาบแรกไม่เกิน ให้ยอมเรียนไปก่อน แล้วพิจารณาคาบถัดไปแทน หากเจอคาบที่น่าเบื่อเกิน aa จึงโดดทีเดียวทั้งหมด pp คาบ (หรือจนหมดวันเรียน)
  • ทำไปเรื่อย ๆ จนกว่าจะพิจารณาครบทุกคาบ (นั่นคือทำได้) หรือใช้สิทธิ์โดดเรียนเกินที่มีอยู่ (นั่นคือทำไม่ได้)

ถึงอย่างไรก็ตาม หากใส่เงื่อนไข "ต้องเข้าเรียนอย่างน้อย 1 คาบในแต่ละวัน" เข้ามา จะพบว่ามีบางกรณีที่มีปัญหา เช่น หาก k=1k=1, p=5p=5 และลำดับที่กำหนดให้คือ 3,2,1,2,33, 2, 1, 2, 3 คำตอบย่อมเป็น 33 เสมอ

สามารถแก้ปัญหานี้ได้โดยทดลองเลือกคาบเรียนที่บังคับว่าต้องเรียน 1 คาบ (สมมุติว่าเลือกคาบ ii โดยต้องน่าเบื่อไม่เกิน aa) แล้วหาว่าจำเป็นต้องโดดเรียนในคาบที่ 11 ถึง i1i-1 กี่ครั้ง (เรียกว่า li1l_{i-1}) และในคาบที่ i+1i+1 ถึง nn กี่ครั้ง (เรียกว่า ri+1r_{i+1}) เพื่อไม่ให้มีคาบใดน่าเบื่อเกิน aa

หากมีค่า ii อย่างน้อยหนึ่งค่าที่ทำให้ li1+ri+1kl_{i-1}+r_{i+1} \leq k แปลว่าเราสามารถหาวิธีโดดเรียนให้ได้ค่าความน่าเบื่อมากสุดไม่เกิน aa

อนึ่ง lil_i และ rir_i สามารถหาได้โดยการ precompute ตาม Greedy Algorithm ที่อธิบายข้างต้นจากซ้ายไปขวาและจากขวาไปซ้าย ตามลำดับ

เรา binary search ทั้งหมด O(log109)O(\log 10^9) ครั้ง แต่ละครั้งต้อง

  • precompute lil_i และ rir_i ใน O(n)O(n)
  • ทดลองเลือกค่า i=1ni=1\dots n ที่ทำให้เงื่อนไขเป็นจริงใน O(n)O(n)

ดังนั้น Time Complexity จึงเป็น O(nlog109)O(n \log 10^9)