zzuli oj 1919(序列分段求和)(二分)
2016-08-18 15:27
176 查看
Description
晴天想把一个包含n个整数的序列a分成连续的若干段,且和最大的一段的值最小,但他有强迫症,分的段数不能超过m段,然后他就不会分了。。。他想问你这个分出来的和最大的一段的和最小值是多少?Input
第一行输入一个整数t,代表有t组测试数据。每组数据第一行为两个整数n,m分别代表序列的长度和最多可分的段数。
接下来一行包含n个整数表示序列。
0<=n<=50000 1<=m<=n,0<=ai<=10000。
Output
输出一个整数表示和最大的一段的最小值。Sample Input
13 21 3 5Sample Output
5HINT
1 3 5 分成一段可以为1 3 5和为9,分成两段可以为1,3 5或者1 3,5,和最大的一段值分别为8,5,所以答案为5Source
haut思路:因为最终所求的值是在0到序列总和sum之间,所以可以用二分查找的方法来查到目标值.
具体看代码:
#include<cstdio> #include<cstring> #include<algorithm> int a[505000]; int n,m,i,j; int judge(int x) { int num=1,ant=0;//没有分割的时候,段数为1. for(i=0;i<n;i++) { if(a[i]>x)//这点特别需要注意,如果单个元素的值大于x(mid),则说明mid偏小 return 0; if(ant+a[i]>x) { num++;//num记录的是所分的段数; ant=a[i]; if(num>m)//如果所分的段数大于m,x(mid)偏小. return 0; } else { ant+=a[i]; } } return 1;//如果 段数小于m,则x(mid)偏大 } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); int sum=0; for(i=0;i<n;i++) { scanf("%d",&a[i]); sum+=a[i]; } int l=0,r=sum; int ans; while(l<=r) { int mid=(l+r)/2; if(judge(mid)) { ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans); } return 0; }
相关文章推荐
- HDU3030最长上升子序列个数+树状数组求和+二分优化
- zzuliOJ 1919:分割序列(二分+限制条件判断)
- zzulioj 1919: D 晴天分段求和
- HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和)
- HDU 2254 奥运(矩阵快速幂+二分等比序列求和)
- HDU 2254 奥运(矩阵高速幂+二分等比序列求和)
- HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和)
- GFOJ686 序列操作(分段DP,未高精)
- 最大连续子序列求和详解
- hdu 4521 小明系列问题——小明序列 线段树+二分
- uvalive2222(等差序列前n项求和)
- POJ 1845 Sumdiv(因子分解+快速幂+二分求和)
- 序列求和
- 序列求和
- |洛谷|二分|P1182 数列分段Section II
- 蓝桥杯入门训练:序列求和
- 二分搜索相关及循环有序序列相关
- BZOJ1046 上升序列 [二分][贪心]
- HDU 1588(数论,构造二分矩阵+求幂运算+二分求和)
- 蓝桥杯备战-序列求和