牛客网 DP34 【模板】前缀和(优质解法)

代码:

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 ]

猜你喜欢

转载自blog.csdn.net/q322359/article/details/135031407