Properties
สมบัติของฟังก์ชันที่ทำ Slope Trick ได้
- เป็นฟังก์ชันต่อเนื่องบนจำนวนจริง
- ฟังก์ชันนั้นสามารถแบ่งออกเป็นฟังก์ชันย่อย แล้วแต่ละฟังก์ชันย่อยเป็นฟังก์ชันเส้นตรงที่มีความชันเป็นจำนวนเต็ม
- ฟังก์ชันนั้นต้องเป็น Convex Function (ฟังก์ชันที่เกิดจุดสูงสุดได้) หรือ Concave (ฟังก์ชันที่เกิดจุดต่ำสุดได้)
ข้อสังเกต ฟังก์ชันที่ทำ Slope Trick ได้มักจะมี
Tutorial
ในการทำ Slope Trick จะใช้ Data Structure ในการเก็บจุดเปลี่ยนความชันของกราฟ โดยอาจใช้ std::multiset
หรือ std::vector
ในการเก็บได้
ค่าที่เก็บใน นั้นจะเป็นจุดเปลี่ยนความชันที่ทำให้ความชันเปลี่ยนไป เช่น
ในการเก็บเส้น นั้นจะเก็บจุดตัดเป็น
ถ้าเพิ่ม เข้าไปอีกเส้นจะทำให้
ฟังก์ชันของสองเส้นนี้รวมกันก็จะเป็น
สังเกตว่า (เส้นสีม่วง) จะมีจุดเปลี่ยนความชันที่ และ และแต่ละครั้งที่เปลี่ยนคือ ทำให้ต้องเก็บจุดนั้น ๆ ครั้ง
ในบางครั้ง ก็อาจจะจำเป็นต้องเก็บ y-intercept (จุดตัดแกน y) และ slope (ความชัน) ร่วมด้วยได้
ในการรวมเส้น เส้นเข้าด้วยกัน y-intercept จะกลายเป็น เมื่อ แทนจุดตัดแกน y ของเส้นที่ และรวมถึง slope ก็จะกลายเป็น เมื่อ แทนความชันของเส้นที่ ด้วย
ปัญหาที่ใช้ Slope Trick ในการแก้
Median (การหาค่ามัธยฐาน)
โจทย์ กำหนดให้ จงหาค่า ที่น้อยที่สุดที่เป็นไปได้
กำหนดให้ ที่มีค่าน้อยที่สุดเมื่อ
ดังนั้น หากกำหนดให้ แล้ว
และเมื่อนิยาม แบบข้างต้นแล้วจะมีค่า ที่ดีที่สุดที่ทำให้ เป็นจุดต่ำสุดของ
จริง ๆ แล้วปัญหานี้สามารถพิสูจน์ได้ว่า
ค่าที่ดีที่สุดของ คือค่ามัธยฐานของ ที่ โดยสามารถไปตามอ่านบทพิสูจน์ได้จาก
Math Stack Exchange
ตัวอย่างการทำงาน
พิจารณา f_2(x)=|10-x|+|8-x|
สังเกตเส้น (เส้นสีแดง) และ (เส้นฟ้า) เมื่อรวมกันจะได้ (เส้นสีม่วง) พอดี
จากนั้นเมื่อใส่ เข้าไปจะได้
(เส้นสีเหลือง) เมื่อรวมเข้ากับ จะได้ (เส้นสีดำ) และเมื่อพิจารณาจุดที่ต่ำที่สุดของ จะได้ค่ามัธยฐานของ ซึ่งมีค่าเท่ากับ และเมื่อแทน ลงไปใน จะได้ค่า ที่น้อยที่สุดที่เป็นไปได้ ซึ่งเท่ากับ
NOI18_Safety
โจทย์(OJ.UZ) มีตึกอยู่ ตึก โดยตึกหมายเลข มีความสูง เมตร โดยตึกทั้งหมดนี้จะปลอดภัยก็ต่อเมื่อ สำหรับทุก ในการทำให้ตึกทุกตึกปลอดภัยนั้นสามารถทำ 2 operation ที่ทำได้ คือ
- ลดความสูงของตึกหมายเลข ลง เมตร
- เพิ่มความสูงของตึกหมายเลข อีก เมตร
ต้องการหาจำนวน operation ที่น้อยที่สุดที่ทำให้ตึกทั้ง ตึกนี้ปลอดภัย
ปัญหาย่อย
จำนวน operation ที่น้อยที่สุดที่ทำให้ และ
ดังนั้นจำนวน operation ในการทำให้ตึกที่ มีความสูง นั้นจะเท่ากับ ดังนั้น
ซึ่งสังเกตได้ว่าเหมือนกับปัญหา Median ด้านบน
ปัญหาเต็ม
จำนวน operation ที่น้อยที่สุดที่ทำให้ และ สำหรับ
ดังนั้น
จำนวน operation ที่น้อยที่สุดที่ยังถูกเงื่อนไขเมื่อ
ทำให้
สังเกตว่า เป็นเส้นสีแดงและ เป็นเส้นสีฟ้า เนื่องจาก เป็นจำนวน operation ที่น้อยที่สุดที่ยังถูกเงื่อนไขเมื่อ กล่าวคือเป็น ที่ขยายไปทางซ้าย และทางขวา
เมื่อใส่เส้นใหม่ไปเรื่อย ๆ ก็จะต้องขยายไปทางซ้าย และขวา ทุกครั้งทำให้ใน Data Structure ของเราจำเป็นต้องเก็บค่า lazy ไว้ด้วย โดยอาจใช้ lazy set มาช่วยได้
Lazy Set
Lazy set สามารถทำการ Implement ได้ด้วย std::set
ธรรมดา (อาจใช้ std::multiset
)
โดยมีการเก็บค่า lazy ไว้ด้วยว่าค่านั้น ๆ จะถูกเปลี่ยนไปเท่าไหร่
หลักการของการใช้ของ lazy set คือ
ในโจทย์ข้อนี้ไม่สามารถใช้ Lazy set เพียง 1 ตัวได้ เนื่องจากต้องการหาค่าที่อยู่ตรงกลางเนื่องจากกราฟเว้าลงมาจนตรงกลางของ Data Structure นั้นทำให้เกิดค่า และเนื่องจากต้องการหาตรงกลางของ Data Structure และในการทำ lazy ค่า จึงสามารถใช้ Lazy set 2 ตัวเพื่อเก็บจุดเปลี่ยนความชันฝั่งซ้ายและขวา
ข้อสังเกต ในการใส่เส้นใหม่แต่ละครั้งทำให้อาจค่าของ ที่ต่ำที่สุดเปลี่ยนไปได้แต่ค่า ไม่สามารถลดลงได้เนื่องจากเพิ่มเส้นใหม่ลงไปเรื่อย ๆ และจำนวน operation ที่ใช้ก็จะเพิ่มขึ้นหรือเท่าเดิมไม่สามารถลดลงได้