區間問題
技巧¶
掃描線角度思考¶
最大交集數量
給 \(n\) 個 interval,兩兩間若有 overlap 則建邊,問 max clique1 大小
hint
找最大 interval 交集的數量,也就是 band width
思路
- 想成掃描線從左掃到右
- 遇到 \(l_i\) 就 +1
- 遇到 \(r_i\) 就 -1
刪除 overlap¶
刪除 overlap
Q1: 給 n 個 interval,若 A ⊆ B2 則刪掉 B
Q2: 給 n 個 interval,若 A ⊆ B 則刪掉 A
Q1 思路
-
按照 \(r_i\) 排序
-
每次跟合法的最後一個 (back) 比較,若 \(l_j \le l_i, i<j\) 則 \(j\) 不合法
code
Q2 思路
-
同理,按照 \(r_i\) 排序
-
從後往前掃,每次跟合法的最前面那個 (front) 比較,若 \(l_j \le l_i, i<j\) 則 \(i\) 不合法
code
例題¶
區間選點¶
區間選點
給 \(n\) 個 \([l_i,r_i]\) 問至少選幾個 point 使得每個 \([l_i, r_i]\) 都有被覆蓋到
\(n \le 2×10^5, l < r \le 10^9\)
思路1
-
我們觀察到第一個要選的 point 一定要至少在一個 \(r_i\) 之前
- 那最前面的 \(r_i\) 肯定是最小的 \(r_i\)
- 那在這個 \([l_i, r_i]\) 上,我應該要選哪個 point 呢?
- 大家的右界都在我的右邊,如果我跟某個區段沒有 overlap 那怎麼選都不可能覆蓋到,若有 overlap 的話選 \(r_i\) 最能 benefit,所以選最右邊 (\(r_i\)) 最好
-
接著我們把 overlap 的 interval 刪掉
-
接下來我們一樣要選至少在一個 \(r_i\) 之前的 point
- 假設我們第一次選了第 \(i\) 個區段的 \(r_i\) 再來再選第 \(j\) 個區段的 \(r_j\)
- 那 \(j\) 這個區段
- 一定沒有跟先前的 \(r_i\) overlap
- 是目前右界最小的
- 也就是按照右界排序,第一個沒有 \([l_i, r_i]\) overlap 的
-
再來就是子問題
思路2
-
先刪除一定不重要的
-
再來 sort 左界或右界都可以
-
再來題目就滿足 \(l_i<l_{i+1},r_i<r_{i+1}\)
-
再來就跟思路1一樣 greedy 的挑就好
全國賽模擬賽 2019 pC
見此處
TIOJ 1408. 我很忙
給 \(n\) 個 interval,有 weight \(w_i\),問至少選幾個 point 使得每個 interval 中至少有 \(k\) 個點被選到
\(n \le 10^5, 0\le l,r,w\le 10^5\)
思路
先將 interval 用 \(r_i\) 小到大 sort,線段樹 0/1 維護有選的點,這樣我們從前往後看時,若這個 interval 中間有選的點還沒有 \(k\) 個的話就二分搜當前的 interval 的最短的 suffix 滿足是 0 的個數 >= k - interval 內是 1 的個數,然後將這個 suffix 上的數字通通改成 1,然後一直做下去就可以了,複雜度 \(O(n \log^2 n)\)。
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
|
區間覆蓋¶
區間覆蓋
給 \(n\) 個 \([l_i,r_i]\) 問至少選幾個 \([l_i, r_i]\) 使得每個 point 都有被覆蓋到,若不行輸出 \(-1\)
\(n \le 2×10^5, l < r \le 10^9\)
思路
-
先刪掉不重要的
-
第一個一定要挑
-
再來繼續從左往右看跟第一個有交集的,選右界最大的
-
直到跑到左界跟第一個沒交集,把選到右界最大的當成第一個,子問題
-
IMPOSSIBLE 的話就是跟第一個沒交集且跟目前右界最大的也沒交集
或是先考慮第一個要挑什麼,我們一定是挑選 \(l_i\) 最小,若還是有很多則挑選 \(r_i\) 最大的,所以可以把前面刪除 overlap 改成用這種方法 sort。
code
full code : http://codepad.org/BnyJUIwV
區間分組¶
區間分組
給定 \(n\) 個 interval,分組使得每組內部兩兩之間沒有交集,並使得組數盡可能小。
\(n\le 2\times 10^5, l_i<r_i\le 10^9\)
實際應用
公司今天有 20 場會議,問最少用幾個會議室可以安排下
思路1
-
將所有區間按照左端點從小到大排序
-
從前往後處理每個區間,判斷能否將其放到某個現有的組中(小頂堆維護右端點(最早結束的區間))
思路2
對於有重疊的部分,我們肯定要將他們分成不同的組,因此我們只要找最大的重疊區間數即可
區間最大獨立集¶
max independent set on interval graph / activity selection problem
給 \(n\) 個 intervals,選一些 intervals,兩兩不 overlap,求最大化選的數量
思路
-
刪除不重要的
-
第一個一定要選,因為他的右界是所有右界裡面最小的
-
刪除跟第一個 overlap 的
-
再挑刪完後的第一個 (子問題)
可證明按照 \(r_i\) 小到大排序,greedy 的取是好的。因為對於後面來說要盡量挑最不會 overlap 的,也就是右界最小的,所以我們將 \(r_i\) 最小的取掉之後,刪除與他 overlap 的 intervals,也就跟我們 greedy 在做的事情一樣了
延伸 (加上權重) : job scheduling problem
CF 1841 D. Pairs of Segments
給 n 個 interval,問最少刪掉幾個 interval 可以滿足
-
有辦法兩兩 pair
-
一個 pair 中的兩個 interval 必須 overlap
-
任意不同 pair 中的 interval 不能 overlap
\(n\le 2000\)
最小刪除¶
例題
刪除最少個 interval,使得 max band width 變小
思路
-
我們把存在 max band width 的區段給找出來,我叫他 target
-
將跟這些 target 沒 overlap 的 interval 給刪掉
-
剩下 sort \(l_i\)
-
target 會有一個指針 j 代表目前在 target[j]
-
interval 會有一個指針 i 代表目前在 interval[i]
-
第一段要選的 interval 須滿足
- 有包含 target[1]
- 右界越大越好
-
我們找到這個 interval 後,看他的 \(r_i\) 可以延伸到第幾個 target
-
在這幾個 target 中,我們都可以去找有跟這些 target overlap 的 interval,存他們之中的最大右界
-
等到 target[j] 已經無法跟第一個選的 interval overlap 後,我們就把當前找到的最大右界當成第一個選的,變成子問題 (有點類似保母問題的維護方式)
-
max clique 最大完全子圖 ↩
-
\(A \subseteq B\),\(A\) 是 \(B\) 的子集 ↩