6580: Splitting Pile

首先是基础知识的补充,什么是前缀和。(此基础知识转自CSND一位大神的文章)

一维前缀和

这个优化主要是用来在O(1)时间内求出一个序列a中,a[i]+a[i+1]+……+a[j]的和。

具体原理十分简单:用sum[i]表示(a[1]+a[2]+……+a[i]),其中sum[0]=0,则(a[i]+a[i+1]+……+a[j])即等于sum[j]-sum[i-1]

二维前缀和

同理,有一维就有二维。对于一个矩阵a,我们也能在O(1)时间内求出子矩阵[x1~x2][y1~y2]的和。

设sum[i][j]为子矩阵[1~i][1~j]的和。则由容斥原理得:

sum[0][j]=sum[i][0]=0

a[x1~x2][y1~y2]=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]

应用问题

核心就两个字:降维

面对许多高维问题,往往前缀和是最先想到的降维方法。 
这样在降维的基础上,许多更进一步的优化才能实现。

题目:

  

6580: Splitting Pile

时间限制: 1 Sec  内存限制: 128 MB
提交: 325  解决: 101
[提交] [状态] [讨论版] [命题人:admin]

题目描述

Snuke and Raccoon have a heap of N cards. The i-th card from the top has the integer ai written on it.
They will share these cards. First, Snuke will take some number of cards from the top of the heap, then Raccoon will take all the remaining cards. Here, both Snuke and Raccoon have to take at least one card.
Let the sum of the integers on Snuke's cards and Raccoon's cards be x and y, respectively. They would like to minimize |x−y|. Find the minimum possible value of |x−y|.

Constraints
2≤N≤2×105
−109≤ai≤109
ai is an integer.

 

输入

Input is given from Standard Input in the following format:
N
a1 a2 … aN

 

输出

Print the answer.

 

样例输入
6
1 2 3 4 5 6

 

样例输出
1

 

提示

If Snuke takes four cards from the top, and Raccoon takes the remaining two cards, x=10, y=11, and thus |x−y|=1. This is the minimum possible value.

解决办法:用一个数组array来存储数据,一个数组sum来存储前缀和,total为所有数据的总和,用total-前缀和 就是剩余部分的和 ,然后再用前缀和 减去 这个剩余部分的和 就是能得到差值,遍历前缀和数组,用total 来一个一个减找到最小的即可

代码:

        

import java.util.Scanner;

/*
 * 前缀和就是前n个元素(n任意)的和
 * 总数减去前缀则就是剩余的数的和
 */
public class SplittingPile {
    static int N;
    static long[] array;    //接收数据的数组
    static long[] sum;        //前缀和数组
    static Scanner input = new Scanner(System.in);
    public static void main(String[] args) {
        N = input.nextInt();
        int length = N + 1;
        array = new long[length];
        sum = new long[length];
        long total = 0;
        for(int i=1;i < N + 1;i ++) {
            array[i] = input.nextLong();
            sum[i] = sum[i - 1] + array[i];
            total += array[i];
        }
        long min = Long.MAX_VALUE;
        for(int i=1;i < N;i ++) {    //注意 因为每个人必须至少拿一个 所以循环求和的时候不能循环到最后一个。
            if(min > Math.abs(sum[i]*2 - total)) {    //total - sum[i]是减去前缀和之后剩余的部分的和,再用sum[i](前缀和)减去 剩余部分的即可得到最小的值
                min = Math.abs(sum[i]*2 - total);
            }
        }
        System.out.println(min);
    }
}

转载于:https://my.oschina.net/u/3900854/blog/1921721

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值