洛谷P1182 数列分段Section II 二分答案

洛谷P1182 数列分段Section II

二分答案
题意:将 n 个 数 分为 m段 求一种方案,使这m段中最大的和 最小
额。。可能有点拗口,其实就是说每一种方案,都有对应的 每段和的最大值,
要求一种方案,使最大值最小

题解 :二分答案 mid为分成的最大值,
然后O(n) 判断 答案 是否可行
贪心的做下去,如果再加上就要超过了,那就新开一段

最后判断开的段数是否小于 m

1、注意要判断 如果当前这个值大于 mid,一个值就已经大于 mid了,那就直接退出
了,否则 ,这个值也只会单独算为一段的,其实他一段都放不下

2、或者还有之中方法 答案从 最大的 a[ i ] 开始枚举。。。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <string>
 6 #include <algorithm>
 7 #include <iomanip>
 8 #include <iostream>
 9 using namespace std ;
10
11 const int maxn = 100011 ;
12 int n,m,l,r,mid ;
13 int a[maxn] ;
14
15 inline bool check( int mid )
16 {
17     int ans = 0,sum = 0 ;
18     for(int i=1;i<=n;i++)
19     {
20         if(a[ i ]>mid) return 0 ;
21 // 1、注意要判断  如果当前这个值大于 mid,一个值就已经大于  mid了,
22 //那就直接退出了,否则 ,这个值也只会单独算为一段的,其实他一段都放不下
23         if( sum+a[ i ] > mid )
24             ans++,sum = 0 ;
25         sum+=a[ i ] ;
26     }
27     ans++ ;
28     return ans <= m ;
29 }
30
31 int main()
32 {
33     scanf("%d%d",&n,&m) ;
34     for(int i=1;i<=n;i++) scanf("%d",&a[ i ]) ;
35     l = 0,r = 1e9 ;
36     while( l<r )
37     {
38         mid = ( l+r )>>1 ;
39         if(check(mid))
40             r = mid ;
41         else
42             l = mid + 1 ;
43     }
44     printf("%d\n",r) ;
45     return 0 ;
46 }
时间: 2024-12-23 01:29:32

洛谷P1182 数列分段Section II 二分答案的相关文章

洛谷 P1182 数列分段Section II Label:贪心

题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列4 2 4 5 1要分成3段 将其如下分段: [4 2][4 5][1] 第一段和为6,第2段和为9,第3段和为1,和最大值为9. 将其如下分段: [4][2 4][5 1] 第一段和为4,第2段和为6,第3段和为6,和最大值为6. 并且无论如何分段,最大值不会小于6. 所以可以得到要将数列4 2 4 5 1要分成3段,每段和的最大值最小为6. 输

P1182 数列分段`Section II`

P1182 数列分段`Section II` 二分答案 初始设l=0,r=1e9 然后二分答案,每次在数列中跑一遍判断是否合法即可. 复杂度 O(n log1e9) (真的要改掉我不检查就交的坏习惯qaq) #include<cstdio> #include<cstring> #include<cctype> using namespace std; inline int Int(){ char c=getchar(); int x=0; while(!isdigit(

P1182 数列分段Section II

P1182 数列分段Section II 题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列4 2 4 5 1要分成3段 将其如下分段: [4 2][4 5][1] 第一段和为6,第2段和为9,第3段和为1,和最大值为9. 将其如下分段: [4][2 4][5 1] 第一段和为4,第2段和为6,第3段和为6,和最大值为6. 并且无论如何分段,最大值不会小于6. 所以可以得到要将数列4 2 4 5

luogu P1182 数列分段Section II

题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列4 2 4 5 1要分成3段 将其如下分段: [4 2][4 5][1] 第一段和为6,第2段和为9,第3段和为1,和最大值为9. 将其如下分段: [4][2 4][5 1] 第一段和为4,第2段和为6,第3段和为6,和最大值为6. 并且无论如何分段,最大值不会小于6. 所以可以得到要将数列4 2 4 5 1要分成3段,每段和的最大值最小为6. 输

洛谷P1182数列分段

题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列4 2 4 5 1要分成3段 将其如下分段: [4 2][4 5][1] 第一段和为6,第2段和为9,第3段和为1,和最大值为9. 将其如下分段: [4][2 4][5 1] 第一段和为4,第2段和为6,第3段和为6,和最大值为6. 并且无论如何分段,最大值不会小于6. 所以可以得到要将数列4 2 4 5 1要分成3段,每段和的最大值最小为6. 输

洛谷 [P1182] 数列分段

这是一道典型的二分答案问题(最大值最小,最小值最大)关键是对于细节的处理. 二分的框架: //l=max{num[i]},r=sum{num[i]} while(l<=r){ int m=(l+r)>>1; if(chk(m)){ r=m-1; }else l=m+1; } cout<<l; 二分的框架是普遍使用的,关键是检验函数的设计,此处的检验函数的含义为: 是否存在一种合法的划分,使得每段的最大值都不大于m. 设计好了检验函数,就要思考l与r的转移:若存在这种合法的划分

洛谷 P1181 数列分段Section I

题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成连续的若干段,并且每段和不超过M(可以等于M),问最少能将其分成多少段使得满足要求. 输入输出格式 输入格式: 输入文件divide_a.in的第1行包含两个正整数N,M,表示了数列A[i]的长度与每段和的最大值,第2行包含N个空格隔开的非负整数A[i],如题目所述. 输出格式: 输出文件divide_a.out仅包含一个正整数,输出最少划分的段数. 输入输出样例 输入样例#1: 5 6 4 2 4 5 1 输出样例#1: 3 说

数列分段Section II

洛谷传送门 输入时处理出最小的答案和最大的答案,然后二分答案即可. 其余细节看代码 1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 int n, m, a[100001], x, y, ans = 100001; 7 8 bool pd(int mid) 9 { 10 int i, sum = 0, tot = 1; 11 for(i = 1; i <= n; i++) 12 { 1

每日一水之 luoguP1182 数列分段Section II

题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列4 2 4 5 1要分成3段 将其如下分段: [4 2][4 5][1] 第一段和为6,第2段和为9,第3段和为1,和最大值为9. 将其如下分段: [4][2 4][5 1] 第一段和为4,第2段和为6,第3段和为6,和最大值为6. 并且无论如何分段,最大值不会小于6. 所以可以得到要将数列4 2 4 5 1要分成3段,每段和的最大值最小为6. 输