前缀和学习笔记

1. 前缀和概述

前缀和是一种预处理技术,通过预先计算数组中从第一个元素到当前元素的累加和,来优化区间查询操作。

2. 一维前缀和

2.1 基本实现

1
2
3
4
5
6
7
8
9
10
11
12
// 构建前缀和数组
void buildPrefixSum(int nums[], int n, int preSum[]) {
preSum[0] = 0; // 注意preSum[0]=0
for(int i = 0; i < n; i++) {
preSum[i + 1] = preSum[i] + nums[i];
}
}

// 查询区间[left, right]的和
int rangeSum(int preSum[], int left, int right) {
return preSum[right + 1] - preSum[left];
}

2.2 经典例题

  1. P8218 【深进1.例1】求区间和
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 使用前缀和求解区间和
    int n, m;
    int a[100005], s[100005]; // a是原数组,s是前缀和数组

    // 构建前缀和数组
    s[0] = 0;
    for(int i = 1; i <= n; i++) {
    s[i] = s[i-1] + a[i];
    }

    // 处理查询
    while(m--) {
    int l, r;
    cin >> l >> r;
    cout << s[r] - s[l-1] << endl;
    }

这是一道非常基础的前缀和模板题,帮助理解前缀和的基本概念和实现。题目直接考察区间查询,是前缀和最基本的应用。

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<bits/stdc++.h>
using namespace std;
int n,a[100100],m,c,d,sum=0,b[100010];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=b[i-1]+a[i];
}
cin>>m;
for(int i=0;i<m;i++)
{
cin>>c>>d;
cout<<b[d]-b[c-1]<<endl;
}
return 0;
}

3. 二维前缀和

3.1 基本实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 构建二维前缀和数组
void build2DPrefixSum(int matrix[][1005], int m, int n, int preSum[][1005]) {
// 初始化preSum为0
for(int i = 0; i <= m; i++) {
for(int j = 0; j <= n; j++) {
preSum[i][j] = 0;
}
}

for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
preSum[i + 1][j + 1] = preSum[i + 1][j] + preSum[i][j + 1]
- preSum[i][j] + matrix[i][j];
}
}
}

// 查询子矩阵和 [(x1,y1), (x2,y2)]
int getRegionSum(int preSum[][1005], int x1, int y1, int x2, int y2) {
return preSum[x2 + 1][y2 + 1] - preSum[x2 + 1][y1]
- preSum[x1][y2 + 1] + preSum[x1][y1];
}

4. 前缀和的应用场景

4.1 适用情况

  • 需要频繁查询区间和
  • 数组元素不会被修改
  • 对查询速度要求高

4.2 复杂度分析

  • 预处理时间复杂度:O(n)
  • 查询时间复杂度:O(1)
  • 空间复杂度:O(n)

5. 进阶应用

5.1 差分数组

差分数组是前缀和的逆运算,常用于区间修改操作。

5.2 前缀和的变种

  1. 前缀积
  2. 异或前缀和
  3. 前缀最大值/最小值

6. 练习题目推荐

  1. P1115 最大子段和 - 一维前缀和的基础应用
  2. P1387 最大正方形 - 二维前缀和的经典题目
  3. P2671 求和 - 前缀和的进阶运用
  4. P1719 最大加权矩形 - 二维前缀和与最大子矩阵和
  5. P3397 地毯 - 二维差分数组的应用

7. 注意事项

  1. 构建前缀和数组时,通常多开一个位置(下标0)
  2. 注意数组下标的处理,特别是区间和的计算
  3. 处理大数据时注意整型溢出问题
  4. 使用数组时要预先定义足够大的空间