一维前缀和
对一个原数组,令
,即称为的前缀和数组
不难发现有以下性质:
- 任意以为起始的子区间,其元素和为
对于满足如下要求的运算:
- 元素间运算满足结合律
- 所有元素具有逆元,即满足消去律(可由运算结果及其中一个操作数得知另一个操作数)
- 满足上述要求的区间信息包括加和、乘积、异或等
令,则有
原地实现:
c++int a[MAXN], t; for (int i = 1; i <= n; ++i) { cin >> t; a[i] += t; a[i + 1] = a[i]; }
二维前缀和
类似一维前缀和,对一个行列的二维数组,令
,即称为的前缀和数组
类似一维前缀和,结合容斥原理,对于特定的运算,任意一个子区间(左上角为,右下角为)的元素和为,其中
原地实现:
c++int a[MAXN][MAXM], t; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { cin >> t; a[i][j] += t; a[i][j + 1] += a[i][j] - a[i - 1][j]; // 容斥 a[i + 1][j] = a[i][j]; } }也可以不依赖容斥,像扫地一样实现(虽然高维前缀和不实用,但这种方法能比较清晰地算出高维前缀和):
c++for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { cin >> t; a[i][j] += t; a[i][j + 1] = a[i][j]; } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { a[i + 1][j] += a[i][j]; } }