前缀数组-截断数组

3956. 截断数组 - AcWing题库

不愧为acwing的中等题,细节是真的多,又又又阴沟翻船了。

题目要我们分成三个数组,求解又集几种分法。普遍思路是首先求解数组总和,除以3求的平均值。

第一个注意点:如果数组给的数的数量不足三个,那么返回0,如果总和除不尽3也返回0

接着我们查找几种分法,原理很简单,只要确定前两段得到分法并相乘就可以得出总分法。

因为不管前两段怎么分,剩下来的都是最后一段。那么关键问题是前两种的分法怎么求,在这里提供一种思路。我们求出前缀和后,找到一段距离,这段距离上的数字的和等于总和的三分之一,这就是第一段的最小分法子,为什么是最小分发?因为后面如果跟着0或者正负8,那么它的长度就会变长,而值不变。问题来了,如何确定第一段的最长的长度,并类推到第二段呢?我们不妨直接设个中间量aaaa,首先在前n-1个数字中寻找累加起来等于average的,找到一个aaaa++,一旦前缀和等于average*2,就证明已经到了第二段的最小长度,这时候就将answer+aaaa,为什么是加aaaa呢,原理就是总数等于第一段的数量乘以第二段的种类数,这是是把乘法变加法。

注意点:

之所以我令编号小于a,不仅仅是因为aa【a】等于average*3,还有一种特殊的样例,三个0,为了规避它的影响的,我设置这个条件,顺便

  if(aa[b]==average*2) {
		  answer=answer+aaaa;
	  }
	  if(aa[b]==average) {
		  aaaa++;
	  }

这一块代码也是规避0 0 0的影响的设置的

好啦,这题目就是这样

总代码:

import java.awt.geom.AffineTransform;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.function.IntBinaryOperator;
import java.util.function.LongBinaryOperator;

import javax.management.relation.InvalidRelationTypeException;

public class Main {
    public static void main(String[] args) throws IOException {
        Scanner sc=new Scanner(System.in);
        BufferedReader br1=new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw1=new PrintWriter(System.out);
       String[] aStrings=br1.readLine().split(" ");
   int a=Integer.parseInt(aStrings[0]);
  aa=new long[a+1];
  String[] bStrings=br1.readLine().split(" ");
  int b;
  long sum=0;
  for(b=1;b<=a;b++) {
	  aa[b]=Long.parseLong(bStrings[b-1]);
	  aa[b]=aa[b]+aa[b-1];
	 
  }
  long average=aa[a]/3;
  if(aa[a]%3!=0||a<3) {
	  System.out.println(0);
	  return;
  }
  long answer=0;
  long aaaa=0;
  for(b=1;b<a;b++) {
	
	  if(aa[b]==average*2) {
		  answer=answer+aaaa;
	  }
	  if(aa[b]==average) {
		  aaaa++;
	  }
  }
  System.out.println(answer);
    }
    public static long[] aa;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值