You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
python/TangDou/Topic/前缀和和差分洛谷题单总结.md

3.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

前缀和和差分洛谷题单总结

参考文献

一、公式

前缀和的公式

一维:s[i] = a[i] + s[i-1]

二维:s[i][j] = a[i][j] + s[i-1] [j] + s[ i] [j-1] - s[i-1][j-1]

差分的公式

一维:b[i] =s[i] - s[i-1]

二维:b[i] = s[i][j] - s[i-1][j]-s[i][j-1]+s[i-1][j-1]

二、题单

P1115 最大子段和

分析 先求每个位置的前缀和(某个区间求和前缀和可以说是最快的),然后去找该位置前前缀和的最小值,如果要求一段和最大,就要用这段和减去前面最小的值。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
int n, a[N], s[N], ans[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i], s[i] = s[i - 1] + a[i]; // 前缀和

    int mi = 0;
    for (int i = 1; i <= n; i++) {
        ans[i] = s[i] - mi;
        mi = min(mi, s[i]);
    }
    int res = -INF;
    for (int i = 1; i <= n; i++) res = max(res, ans[i]);
    cout << res << endl;
    return 0;
}

P3397 地毯

分析 看到这里的时候,我就想到了一个矩阵的某个子矩阵进行加减,瞬间想到二维差分和二位前缀和,二位差分的公式为:

由差分算的二位前缀和公式:

#include <bits/stdc++.h>
using namespace std;

const int N = 1010;
int b[N][N], s[N][N];
int n, m;

int main() {
    cin >> n >> m;
    while (m--) {
        // 从0开始构建差分数组
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        b[x1][y1] += 1; // 进行子矩阵的加减,差分
        b[x2 + 1][y1] -= 1;
        b[x1][y2 + 1] -= 1;
        b[x2 + 1][y2 + 1] += 1;
    }
    // 还原为原始数组
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            s[i][j] = b[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1]; // 把之前的加减结果进行求和
            printf("%d ", s[i][j]);                                          // 注意输出格式,每个数带一个空格
        }
        printf("\n"); // 结束一行的输出输出一个换行符号
    }
    return 0;
}

P3406 海底高铁

分析 ① 每一段的最小费用加起来则总体费用最小。

② 这里的区间是线段而不是一个具体的数,所以我们需要以一个统一的标准进行区间段的区分:于是我们想到了以每个区间的左端点值进行整个线段的记录。

③ 节约时间可以对某段区间做同样的加减数的方法:想到的就是差分(当然有差分就会有由差分求前缀和)。

④ 最后用得到的线段数比较两种购买方案。

注意 当然代码中还有很多需要记录的细节!!!例如:线段数是站点数-1同时差分和前缀和的循环最好是从1开始涉及边界问题