鼠鼠的算法题解(前缀和)

import java.util.*;
public class BiggestSum3260 {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);

        int t = s.nextInt();//样例个数//
        long []a = new long [(int)1e5*2+5];
        for(int i = 0; i < t; i ++){
            int n = s.nextInt();
            int k = s.nextInt();

            for(int j = 1; j <= n ; j ++){
                a[j] = s.nextLong();
            }

            Arrays.sort(a,1,n+1);//宝石价值升序排序//

            for(int j = 1; j <= n; j ++){
                a[j] += a[j-1];//a[j]表示前j项的和//
            }
            long sum;
            long max = 0;

            for(int left = 0,right; left <= 2*k ; left+=2){
                right = n-(k-left/2);
                sum = a[right] - a[left];
                max= Math.max(max,sum);
            }
            System.out.println(max);
        }
    }
}

又是被算法题折磨的一天。

前缀和总结

昨天学习了前缀和知识,一直似懂非懂。练了两道例题才稍有理解。所谓的前缀和,就是经过预处理(时间复杂度为O(n))后,能使m次查询(l,r)区间上元素之和的时间复杂度每次均为O(1),总复杂度为O(n+m);而普通暴力算法下的时间复杂度为O(n*m)。也就是说它降低了区间多次求和的时间复杂度。因此,在遇到较大的n和m时,我们可以使用前缀和来优化。

前缀和模版

前缀和的模版就是创建一个数组sum[],使得sum[i]等于数据数组a[]的前i项和,(l,r)区间之和就等于sum[r]-sum[l-1]。sum数组本身的递推为:sum[i] +=sum[i-1] + a[i-1](当前项=前一项+差分项)。考虑到数组越界的可能,我们在给sum数组赋值时索引从1开始,到n结束。

例题分析

下面说说本题。作为一名刚接触了一点基础算法的大一鼠鼠,我的第一反应是利用贪心,比较两个最小值与一个最大值谁更小,从局部最优推至全局最优。但是,运行后在所给样例中的倒数第二个发生错误,按照贪心的思路应该是先取前两个最小值,再取最大值,最后结果为40。然而,连续去除两次最大值能得到更优的结果46,尽管它并没有做到局部最优。所以改变思路使用暴力枚举出所有结果取最大值。参考了一下题解的思路,发现宝石的价值其实就是去头去尾后,中间一段区间宝石的价值和(如下图),顺理成章地使用前缀和算法,求出区间长度,比较后得到结果。

  • 13
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值