(坚持每天写算法)算法学习与复习part1基础算法part1-10——前缀和
题目详情:

这一道题要使用前缀和,我们对前缀和的定义从从开头到某一个结尾的区间和。
假设有这么一种情况:
原数组: a[1], a[2], a[3], a[4], a[5], …, a[n]
前缀和 Si为数组的前 i项和
前缀和: S[i] = a[1] + a[2] + a[3] + … + a[i]
(需要注意的是,前缀和下标统一的从1开始,每次写数组都问一下自己这道题的原始模板下标是从哪里开始的,话说这就是背板吧,这样子做是为了下标混乱)
前缀和分为一维和二维的,可以求解某一段区间的和,一维度的求解某个区间的和可以这么算:S[r] - S[l - 1]
直接贴上一维的利用前缀和求解某一段区间的和代码:
#include<iostream> using namespace std; const int N = 100010; int n,m; int a[N] , s[N]; int main(){ cin>>n>>m; //按惯例,前缀一定要是一个1 for(int i = 1 ; i <= n ; i++){ cin>>a[i]; } for(int i = 1 ; i <= n ; i ++){ s[i] = s[i-1] + a[i]; } while(m--){ int l,r; cin>>l>>r; printf("%d\n",s[r] -s[l-1]); } return 0; }
然后我们开始探究二维的代码:
这里是图解:

由于那么求出前缀和就可以求解二维的某段区间的值了,这里是图解:

这里是二维的代码:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int N = 1010; int n , m , q;// int s[N][N];//应该不会爆,int的范围是10位数,加法应该不会 int main(){ scanf("%d%d%d" ,&n,&m,&q); for(int i = 1 ; i <= n ; i ++){ for(int j = 1 ; j <= m ; j ++){ cin>>s[i][j]; } } for(int i = 1 ; i <=n ; i ++){ for(int j = 1 ; j <= m ; j ++){ s[i][j] += s[i][j-1] + s[i-1][j] -s[i-1][j-1]; } } while(q--){ int x1,x2,y1,y2; cin>>x1>>y1>>x2>>y2; printf("%d\n" , s[x2][y2] - s[x2][y1-1]-s[x1-1][y2] + s[x1-1][y1-1]); } return 0; } // 要点:一维前缀和,尝试二维前缀和,也就是前缀和矩阵 // 知道如何算出二维前缀和矩阵,并且在代码中展示出来,这里采用了快捷方法 // 知道如何通过前缀和矩阵算出子矩阵和
时间复杂度:看代码,粗略地猜测,分别是O(n)和O(n^2)。

浙公网安备 33010602011771号