1. 程式人生 > 其它 >離散化與區間合併

離散化與區間合併

技術標籤:演算法演算法

文章目錄

離散化

作用

適用問題:
需要開闢長度很大的陣列統計資料(109),但實際使用的元素個數很少(105
解決方法:
當值域大,但是個數小的一組數,可以通過離散化,將值對映為下標來縮小範圍

例如:
a[ ] : 1, 3, 100, 2000, 500000
↓↓↓↓↓
01234

步驟

  1. a[ ]中可能有重複元素,進行去重(一對一對映)
  2. 計算x離散化後的值(先排序後二分提高查詢效率)注意:離散後用到字首和時,二分返回的應是下標+1(字首和從i = 1開始)

程式碼

vector<int> alls; // 儲存所有待離散化的值
sort(alls.begin(), alls.end()); // 將所有值排序 alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 去掉重複元素 // 二分求出x對應的離散化的值 int find(int x) // 找到第一個大於等於x的位置 { int l = 0, r = alls.size() - 1; while (l < r)//注意不是<=,最後l=r,<=死迴圈 { int mid = l + r >> 1; if (alls[mid]
>= x) r = mid; else l = mid + 1; } return r + 1; // 對映到1, 2, ...n }


區間合併

作用

把若干個區間合併成多個沒有交集的區間

步驟

  1. 按區間左端點排序
  2. 分類討論
    a. 新區間為原區間的子區間
    b. 新區間跟原區間有交集
    c. 新區間跟原區間無交集

程式碼

typedef pair<int, int> PII;

// 將所有存在交集的區間合併
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; }

PS

感謝y總帶我入門,y總yyds!O(∩_∩)O