代码:
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int n=in.nextInt();
int q=in.nextInt();
int[]arr=new int[n+1];
for(int i=1;i<=n;i++){
arr[i]=in.nextInt();
}
//计算数组 arr 对应的前缀和数组
long[]dp=new long[n+1];
for(int i=1;i<=n;i++){
dp[i]=dp[i-1]+arr[i];
}
while(q!=0){
int l=in.nextInt();
int r=in.nextInt();
System.out.println(dp[r]-dp[l-1]);
q--;
}
}
}
}
题解:
该题是前缀和类型最简单的题,就是用来认识前缀和这个方法的
解决该题有很简单的暴力解法,时间复杂度是O(nq),直接按输入的范围进行遍历得到结果,要求查询多少次就遍历多少次,但在该题中用暴力解法必定会超时
对于频繁计算一个区间的数据和,我们通常可以采用前缀和的方法来解决该问题,前缀和的思想有点像动态规划,我们可以创建一个数组 dp ,存储从起点到该位置的数据和,比如在该题中,我们可以创建一个大小为 n+1 的数组 dp ,dp[ i ] 就表示从 1 下标到 i 下标的数据总和
以数据 1,2,4,5,7,6 为例 ,根据题意我们知道,在题目中,数组的下标从 1 开始,而我们的 dp 数组的下标也应该从 1 开始(为了消除边界问题,后面会提到),在 dp 数组中,假设我们要计算 dp[ i ] 的值,也就是说要获取下标 1~ i 的数据和,我们可以先获取 1~ i-1 的值也就是 dp[ i-1 ],再加上arr[ i ],所以我们得出填充 dp 数组的方程 dp[ i ] = dp[ i-1 ] + arr[ i ] ,因为当 i =0 时 dp[ 0 ] = dp[ -1 ] + arr[ 0 ],出现越界,所以 dp 数组从下标 1 开始
填充完 dp 数组后,我们便要使用 dp 数组来解决问题,假设 l =3,r = 5,要获取下标 3~5 的数据和,我们可以用 1~5 的数据和 dp[ 5 ] 减 1~2 的数据和 dp[ 2 ],即 dp[ r ] - dp[ l-1 ],所以我们要获取的结果 result = dp[ r ] - dp[ l-1 ]