前缀和
一维前缀和
思想:假设有原数组a1,a2,a3….an;
求前缀和si
则si = a1 + a2 + … + ai;
若要求区间[l,r]之间的前缀和,则只需将r的前缀和减去l - 1的前缀和即可
时间复杂度为O(1);
模板
#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <cstdio>
using namespace std;
const int N = 100010;
int q[N]; int s[N]; int main() { int n,m; scanf("%d %d", &n,&m);
for (int i = 1;i <= n;++i) scanf("%d", &q[i]);
for (int i = 1;i <= n;++i) s[i] = s[i - 1] + q[i];
while (m--) { int l, r; scanf("%d %d", &l, &r); printf("%d\n", s[r] - s[l-1]); } return 0; }
|
二维前缀和
思想:有一二维数组q,将其看作一个长方形,其二维前缀和s[ i ] [ j ]就是从a[0] [0] 至 a [i] [j] 所有元素的和,
如果想要快速得到每一个s[ i ] [ j ],可以用公式推得
s[i] [j] = s[i - 1] [j] + s[i] [j - 1] - s[i - 1] [j - 1] + a[i] [j];
如果想要求出特定长方形x1,y1至x2,y2的长方形前缀和
则可以利用公式
sum = s[x2] [y2] - s[x1 - 1] [y2] - s[x2] [y1 - 1] + s[x1 - 1] [y1 - 1]
模板
#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream>
using namespace std;
const int N = 10010;
int q[N][N]; int s[N][N];
int main() { int n, m,k; scanf("%d%d%d", &m, &n, &k); for (int i = 1;i <= m;++i) { for (int j = 1;j <= n;++j) scanf("%d", &q[i][j]); } for (int i = 1;i <= m;++i) for (int j = 1;j <= n;++j) s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i-1][j-1]+q[i][j]; while (k--) { int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); printf("%d\n", s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]); } return 0; }
|