離散化與區間合併
阿新 • • 發佈:2020-12-29
文章目錄
離散化
作用
適用問題:
需要開闢長度很大的陣列統計資料(109),但實際使用的元素個數很少(105)
解決方法:
當值域大,但是個數小的一組數,可以通過離散化,將值對映為下標來縮小範圍
例如:
a[ ] : 1, 3, 100, 2000, 500000
↓↓↓↓↓
01234
步驟
- a[ ]中可能有重複元素,進行去重(一對一對映)
- 計算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
}
區間合併
作用
把若干個區間合併成多個沒有交集的區間
步驟
- 按區間左端點排序
- 分類討論
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