1. 程式人生 > 其它 >離散化和區間合併演算法

離散化和區間合併演算法

離散化:

離散化的本質,是對映,將間隔很大的點,對映到相鄰的陣列元素中。減少對空間的需求,也減少計算量。

其實對映最大的難點是前後的對映關係,如何能夠將不連續的點對映到連續的陣列的下標(陣列存的是座標軸上的位置)。此處的解決辦法就是開闢額外的陣列存放原來的陣列下標,或者說下標標誌,本文是原來上的數軸上的非連續點的橫座標。
此處的做法是是對原來的數軸下標進行排序,再去重,為什麼要去重呢,因為本題提前考慮了字首和的思想,其實很簡單,就是我們需要求出的區間內的和的兩端斷點不一定有元素,提前加如需要求字首和的兩個端點,有利於我們進行二分搜尋,其實二分搜尋裡面我們一般假定有解的,如果沒解的話需要特判,所以提前加入了這些元素,從而導致可能出現重複元素。

模板:

vector<int> alls; // 儲存所有待離散化的值
sort(alls.begin(), alls.end()); // 將所有值排序
alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 去掉重複元素

// 二分求出x對應的離散化的值
int find(int x)
{
int l = 0, r = alls.size() - 1;
while (l < r)
{
int mid = l + r >> 1;
if (alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r + 1;
}

認識下pair< , > 逗號兩邊各存一個型別,呼叫第一個用first,第二個用sceond。若對pai型別排序,率先排序的是左邊的型別,然後再排序右邊的型別。

auto型別:自動識別型別。

for(auto item : pp) :這個語法大致意思是用item來遍歷pp中的元素。

區間合併:

模板:

// 將所有存在交集的區間合併
void merge(vector<PII> &segs)
{
vector<PII> res;

sort(segs.begin(), segs.end());

int st = -2e9, ed = -2e9;
for (auto seg : segs)
if (ed < seg.first)
{
if (st != -2e9) res.push_back({st, ed});
st = seg.first, ed = seg.second;
}
else ed = max(ed, seg.second);

if (st != -2e9) res.push_back({st, ed});

segs = res;
}