第一章:5.前缀和
- 软件开发
- 2025-09-18 13:39:01

用空间替换时间的算法、
1.【模板】前缀和#include<iostream> using namespace std; //f[N]为相加,a[i]最大数到10的九次方,有越界的风险 typedef long long LL; const int N = 1e5 + 10; int a[N]; LL f[N]; int n, q; int main() { cin >> n >> q; for (int i = 1; i <= n; i++)cin >> a[i]; for (int i = 1; i <= n; i++) { f[i] = f[i - 1] + a[i]; } while (q--) { int l, r; cin >> l >> r; cout << f[r] - f[l - 1] << endl; } return 0; }
使用暴力解法的话,会超出时间限制
f[i] 表示前i位的和
核心代码:
for (int i = 1; i <= n; i++) { f[i] = f[i - 1] + a[i]; }
2. P1115 最大子段和 - 洛谷 #include<iostream> using namespace std; typedef long long LL; int n; const int N = 2e5 + 10; LL a[N]; LL f[N]; int main() { cin >> n; for (int i = 1; i <= n; i++)cin >> a[i]; for (int i = 1; i <= n; i++) { f[i] = f[i - 1] + a[i]; } LL ret = -1e20;//最终结果 LL premin = 0;//前i个最小前缀和 for (int i = 1; i <= n; i++) { ret = max(ret, f[i] - premin); premin = min(premin, f[i]); } cout << ret << endl; return 0; }运用前缀和算出f[i]
用f[i] 减去 【1,i-1】之间的最小值即可
更新下一个位置的premin最小值
3.【模板】二维前缀和#include<iostream> using namespace std; typedef long long LL; int n, m; int q; const int N = 1e3 + 10; int a[N][N]; LL f[N][N]; int main() { cin >> n >> m >> q; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> a[i][j]; } } //实现二维前缀和 for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + a[i][j]; } } while (q--) { int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; LL ret = f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1]; cout << ret << endl; } return 0; } 4.P2280 [HNOI2003] 激光炸弹 - 洛谷
#include<iostream> using namespace std; typedef long long LL; int n, m; const int N = 5e3 + 10; int a[N][N]; int f[N][N]; int main() { cin >> n >> m; //输入摧毁目标 while (n--) { int x, y, v; cin >> x >> y >> v; x++, y++;//由于是从1开始存取数据,所以坐标都要+1 a[x][y] += v; } n = 5010; //实现二维前缀和 for (int i = 1; i <= N-1; i++) { for (int j = 1; j < N; j++) { f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + a[i][j]; } } //枚举法开始轰炸 int ret = 0;//最终结果 m = min(m, n); //列举每一个正方形,右下,左上 for (int x2 = m; x2 <= N-1; x2++) { for (int y2 = m; y2 <= N-1; y2++) { int x1 = x2 - m + 1, y1 = y2 - m + 1;//左上角的坐标 ret = max(ret, f[x2][y2] - f[x2][y1 - 1] - f[x1 - 1][y2] + f[x1 - 1][y1 - 1]); } } cout << ret << endl; return 0; }