1. 程式人生 > 其它 >2021-1-10(補8號),ACM的day_3

2021-1-10(補8號),ACM的day_3

前言

美好的一天從寫部落格開始


一、繼續學習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的最後一位1lowbit(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;
}