1、一维前缀和
给了你n个非负整数,分别记为第1个数字至第n个数字,查询q次,询问第f个数到第t个数之间所有数字的和。
Input:输入的第一行包含两个整数n,q( 1≤n,q≤105 ),含义如题面所示;第二行包含n个非负整数,每个数字均不超过109;下面q行,每行包括两个数字f,t(1≤f≤t≤n),含义如题面所示。
Output: 对于这q行中的每一行,请你输出一个数字f,t之间的和,包含f t
Sample Input:
9 4
1 3 4 6 2 5 1000000000 1000000000 1000000000
1 6
7 9
3 5
4 4
Sample Output:
21
3000000000
12
6
1、前缀和:前缀和是一个数组的某项下标之前(包括此项元素)的所有数组元素的和。
2、差分是一个数组相邻两元素的差,一般为下标靠后的减去靠前的一个。设差分数组p[],即:p[i]=a[i]-a[i-1]。
本题思路: 两个数组,一个存放这n个数 li,一个存放数组的和 li_sum,li_sum[i]存放li中位置 <=i 的所有数之和,为方便计算,两个数组的第0个位置存0。计算区间[a,b]之间的和时,直接li_sum[b] - li_sum[a-1]即可
n, q = map(int, input().split())
li = []
li = list(int(x) for x in input().split())
li.insert(0,0)
li_sum = [ 0 for i in range(n+1)]
for i in range(1,n+1) :
li_sum[i] = li_sum[i-1] + li[i]
for j in range (q):
a, b = map(int, input().split())
print(li_sum[b] - li_sum[a-1])
2、子矩阵求和
给出一个 n 行 m列的矩阵,矩阵的每个位置有一个非负整数 a[i][j],有 q 次询问,每次询问求一个左上角为 (a,b),右下角为 (c,d)的子矩阵的所有数之和。
Input : 第一行两个整数 n,m,表示矩阵的行和列的大小。接下来 n 行每行 m 个整数,矩阵内容。接下来一行为一个整数 q,表示询问次数。接下来 q 行每行 4个整数 a,b,c,d,含义见题面。
Output : 共 q 行,第 i行为第 i个询问的答案。nxm<100,000 , a[i][j] < 1000 ,q < 100,000 ,1≤a≤c≤n,1≤b≤d≤m。
Sample Input :
3 5
1 2 3 4 5
3 2 1 4 7
2 4 2 1 2
3
1 1 3 5
2 2 3 3
1 1 3 3
Sample Output :
43
9
20
二维前缀和思想:sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+arr[i][j]
本题思路:数组存放矩阵的和matrix_sum,原本是一个二维数组,现拉伸成一维数组a2[i*m+j]=a1[i][j],为方便计算,原本的矩阵加上全为0的第0行和第0列,(a,b)(c,d)两个坐标将(1,1)(c,d)之间的区域分成了四个部分,求的是右下角矩阵的所有元素和,所以应是总的-左下-右上+左上。
#include <stdio.h>
#include <malloc.h>
int main(){
int n, m, q, x1, x2, y1, y2;
int i , j, tmp, res, res1, res2, res3, res4;
int *arr;
scanf("%d %d", &n, &m);
n ++;
m ++;
int *matrix_sum = (int *) malloc(n * m * sizeof(int));
int *sum = (