2021-1-10(補8號),ACM的day_3
阿新 • • 發佈:2021-01-12
前言
美好的一天從寫部落格開始
一、繼續學習ing
1.字首和
一維字首和
S[i] = a[1] + a[2] + ... a[i]
a[l] + ... + a[r] = S[r] - S[l - 1]
二維字首和
S[i, j] = 第i行j列格子左上部分所有元素的和
以(x1, y1)為左上角,(x2, y2)為右下角的子矩陣的和為:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]
2.差分
一維差分
給區間[l, r]中的每個數加上c:B[l] += c, B[r + 1] -= c
二維差分
給以( x1, y1)為左上角,(x2, y2)為右下角的子矩陣中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c
3.位運算
位運算
求n的第k位數字: n >> k & 1
返回n的最後一位1:lowbit(n) = n & -n
4.雙指標
雙指標演算法
for (int i = 0, j = 0; i < n; i ++ )
{
while (j < i && check(i, j))
j ++ ;
// 具體問題的邏輯
}
常見問題分類:
(1) 對於一個序列,用兩個指標維護一段區間
(2) 對於兩個序列,維護某種次序,比如歸併排序中合併兩個有序序列的操作
5.離散化
//離散化
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)
{
int mid = l + r >> 1;
if (alls[mid] >= x)
r = mid;
else
l = mid + 1;
}
return r + 1; // 對映到1, 2, ...n
}
6.區間合併
// 區間合併
// 將所有存在交集的區間合併
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;
}