跳转至

前缀和

一维前缀和

前缀和可以简单理解为「数列的前项的和」,是一种重要的预处理方式,能大大降低查询的时间复杂度。

利用前缀和可以在常数时间复杂度中查询区间和

例题,P8218 【深进1.例1】求区间和

题意,m 次询问,每次输出 [l, r] 的区间和

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

int a[N], n, m;
long long s[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for (int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i];

    cin >> m;
    while (m--) {
        int l, r;
        scanf("%d%d", &l, &r);
        printf("%lld\n", s[r] - s[l - 1]);
    }

    return 0;
}

二维前缀和

例题,P1719 最大加权矩形

题意,输入最大子矩阵和,n <= 120

#include <bits/stdc++.h>

using namespace std;

const int N = 150;

int a[N][N], s[N][N], n;

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) cin >> a[i][j];

    for (int i = 1; i <= n; i++)
        for (int j = 1;  j <= n; j++) 
            s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];

    int ret = -2e9;
    for (int xa = 1; xa <= n; xa++)
        for (int ya = 1; ya <= n; ya++)
            for (int xb = xa; xb <= n; xb++)
                for (int yb = ya; yb <= n; yb++) 
                    ret = max(ret, s[xb][yb] - s[xa - 1][yb] - s[xb][ya - 1] + s[xa - 1][ya - 1]);


    cout << ret << '\n';

    return 0;
}

总结

下标,都必须从 1 开始,否则,代码不好写