二分系列之数列分段

P1182 数列分段 Section II - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这个题目有点小坑。

我们使用二分答案,记住最小值选取我们数组里的最大值,要不然就要在二分的检验函数里建一个判断(就是不允许单个数值大于我们二分的数值),此题我们二分答案,二分得到值后,我们对数组里的数分组


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.TreeSet;
public class Main {	
  public static void main(String[] args) throws NumberFormatException, IOException  {
Scanner sc=new Scanner(System.in);
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String[] aStrings=br.readLine().split(" ");
aa=Integer.parseInt(aStrings[0]);
bb=Integer.parseInt(aStrings[1]);
String[] bStrings=br.readLine().split(" ");
int a;
long b=0;
long c=0;
dp=new int[aa];
for(a=0;a<aa;a++) {
	dp[a]=Integer.parseInt(bStrings[a]);
	c=Math.max(c, dp[a]);//左边界选取数组里最大的数
	b=b+dp[a];//右边界累加和
}

long answer=0;
while(c<=b) {
	long mid=(c+b)>>>1;//二分答案
    if(check(mid)==0) {
    	c=mid+1;
    	//System.out.println("AA"+mid);
    }

    else {
    	answer=mid;
    	//System.out.println(answer);
    	b=mid-1;
    }
}
System.out.println(answer);
	}
  public static int[] dp;
  public static int aa; 
  public static int bb;//最多分几组
  public static int check(long a) {
	  int b;
	  int c=1;
	  long d=0;
	  for(b=0;b<aa;b++) {
		  if(dp[b]>a) {//如果单个数字大于我们二分的值,结束
			  return  0;
		  }
		  d=d+dp[b];
		  if(d>a) {
			  c++;
			  d=dp[b];
		  }
	  }
	  if(c>bb) {
		  return 0;
	  }
	  else  {
		  return 1;
	  }
	 
  }
}

本题注意,我们使用最佳情况来分组,可能我们得最佳情况比标准要小。举个例子

5个数分5个组1 3 3 3 4当我们每组之和为4时分为4个组小于5,当我们变为3时,最优分组会无法fen因为4大于3,但是当我们为4时,我们不采用最优分组,可以得到5组。

所以我们合并情况。把等于和小于合成一组,来不断改变值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值