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];//目标数组,因为下标从1开始,所以多给1
            int index=1;//获取输入值的下标
            while(index<n+1){//获取,从1开始,那么结尾也就自然到了n
                arr[index++]=in.nextInt();
            }
            long[] db=new long[n+1];//前缀和数组,因为默认是0,所以第一个不用处理-->因为有累加和的存在,怕值太大
            index=1;//遍历,求前缀和,从1下标开始
            while(index<n+1){
                db[index]=db[index-1]+arr[index];//所以第一个元素就是0+arr[1]了
                index++;
            }
            //现在有了数组,和数组长度,及其要查询的次数q,及前缀和数组db
            //现在开始处理q次查询了
            while(q>0){//只有--到1的时候,再--一次到0才会出循环
                int l=in.nextInt();
                int r=in.nextInt();
                System.out.println(db[r] - db[l-1]);//输出区间和即可
                q--;//次数--
            }
        }
    }
}

暴力解法:

每一次都求对应区间的和即可,时间复杂度O(N*q)

前缀和:

能快速求出数组中某一个区间的和,这个就是前缀和的作用,与题意符合,所以可以使用

步骤:我们下面的数组下标都从1开始的,不从0开始,原因后面讲

1,预处理出来一个前缀和数组:dp[]

这个数组满足

1.1--->dp[i]表示arr数组中的前i个下标元素的和

如:dp[4]表示arr数组中的前第1,2,3,4个下标的元素和

1.2--->dp[i]=dp[i-1]+arr[i]

2,使用前缀和数组dp[ ]

我们要求的[L,R]的所有元素和:可以用dp[R]-dp[L-1]来表示,直接找到对应下标相减即可

===》现在问题就来了,为什么我们的下标要从1开始,

如果我们从0开始的话dp[L-1]=dp[0-1]=dp[-1],那不就越界了吗,所以不是从0开始的下标

若是题目要求下标从0开始的话,我们可以把这种情况单独拎出来,if(L-1==-1),为dp[0]=0;

[0,R]直接就是dp[R]了不用减一个数了