1. 程式人生 > 其它 >AcWing 906. 區間分組

AcWing 906. 區間分組

題目傳送門

首先我們再來熟悉一遍題目:

我們有\(n\)個區間\(a[i]\)~\(b[i]\),我們將這些區間進行一個分組操作,而這種操作只按照一種標準,就是,每一組內部的區間不能存在交集。
以此標準,讓我們求出最小組數。

注意一點,只要組內所有的區間不存在交集就可以算是一個組,詳情看下圖:

所以你看,很神奇吧這道題,別看這有那麼多的區間,其實只要按照題目要求來進行操作分組,最後分的組可能不是你想象的那樣,如果和你想的不一樣,那麼,只能說是自己想錯了,而不是題目本身錯了,建議,多理解理解題目含義,我就是讀了好多遍題目,才理解了這道題目,然後才理解了\(y\)總視訊講課的內容。

下面我們來看看該怎麼做這道題目
方案:

步驟一
我們首先要做的一步是排序,讓後面的操作更好梳理,這裡按左端點排序。(本人也沒對這種選法理解通透,如果理解清了,會來更新的。)

個人對區間選點的理解

選擇左端點:需要與前面的區間進行比較

選擇右端點:需要與後面的區間進行比較

(注:是指在思考問題,確定方案的時候,不是在寫程式碼的時候)

步驟二

我們要做的就是列舉每個區間,看看當前區間是不是和現有的組存在交集。【或者理解為:我們看看每一個組的最後一個區間是否和當前這個區間是不是有交集。】

由這種判斷方式,我們可以進行如下兩種操作:

1、如果當前列舉到的這個區間和某一個組沒有交集,我們就把他放入這個組內。【即:當前區間左端點大於現在某個組的右端點,我們將這個區間歸為這一組,注意更新組的右端點】

2、如果當前列舉到的這個區間和現有的所有的組都有交集,我們就不能將這個區間歸到組內,而是要給他新開一個組。【即,當前區間的左端點小於或等於現有的所有組的右端點,我們就從新開一個組】

我們按左端點從小到大遍歷,再將每個區間的左端點 range[i].l 與每一組的最右端點的最小值 heap.top() 比較: 若 heap.top() >= range[i].l 或 heap 為空,則說明沒有一組集合可以包含該區間,因此建立新的分組 heap.push(range[i].r) ; 若 heap.top() < range[i].l,說明有分組可以包含該區間,我們預設把該區間加入到第一個分組中(第一個分組的右端點值較小,這樣可以使每個分組包含儘量多的區間),然後從 heap 中彈出第一個分組的右端點值,並用 range[i].r 更新第一個分組的右端點。