AtCoder 🟢 ABC439E Kite
題目的難度顏色使用 Luogu 上的分級,由簡單到困難分別為 🔴🟠🟡🟢🔵🟣⚫。
🔗 ABC439E Kite
Problem Statement
題目簡述
個人在河岸邊放風箏。第 個人站在點 ,其風箏位於點 。
若兩人的風箏線(連接人與風箏的線段)有交點(包含端點接觸),則他們不能同時放風箏。
求最多能有多少人同時放風箏。
Constraints
約束條件
思路:二維LIS
問題轉化:線段不相交的條件
每個人 對應一條從 到 的線段。我們需要找出最大的人數集合,使得這些人的線段兩兩不相交。
線段不相交的條件
考慮兩個人 和 ,假設 (人 站得更靠左):
- 若 :線段 整體在線段 的「左邊」,不相交 ✓
- 若 :線段會在中間交叉,相交 ✗
因此,不相交的條件是:
轉化為 LIS
將所有人按 由小到大排序後,問題變成:
- 在排序後的序列中,選擇最多的人,使得他們的 值嚴格遞增。
這正是 最長嚴格遞增子序列 (Longest Strictly Increasing Subsequence, LIS) 問題!
處理 相同的情況
當 時,這兩條線段的起點相同(端點接觸),因此也算相交,不能同時選取。
排序的關鍵技巧
排序時使用 key = (A_i, -B_i):
- 主鍵 升序
- 次鍵 (即 降序)
這樣處理的目的是:當 相同時, 較大的在前面先被處理。由於我們求的是嚴格遞增的 LIS,同一個 值下最多只會有一個被選入。
使用二分搜尋優化 LIS
程式碼使用經典的二分搜尋優化 LIS 算法:
- 維護陣列
f,其中f[i]表示長度為 的 LIS 的最小末尾元素 - 對每個 ,使用
bisect_left找到插入位置並更新f - 最終
len(f)即為 LIS 的長度
複雜度分析
- 時間複雜度:(排序 + 二分搜尋 LIS)
- 空間複雜度:(儲存輸入和 LIS 陣列)
Code
1 | from bisect import bisect_left |
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 十六個天亮!
評論
WalineGiscus












