【二分】划分数列

来源:互联网 发布:象神佛牌禁忌知多少 编辑:程序博客网 时间:2024/06/06 02:32

划分数列(seq.pas/c/cpp)

【题目描述】

给你一个有n个元素的数列,要求把它划分成k段,使每段元素和的最大值最小

【输入格式】

第一行两个正整数n,k

第二行为此数列ai

【输出格式】

一行一个数,为题目所求答案

【样例输入】

5 2

2 1 3 4 5

【样例输出】

9

【数据规模】

30%数据 n <= 30, k <= 10

100%数据 n <= 100000, k <= n, ai <= 10^9

150%数据 n <= 100000, k <= n, |ai| <= 10^9(附:这50分超越了noip难度,大家可以无视)

【时限】

1s

 

 

最后5个点未完成。目测是单调性优化的动态规划。

简单的二分。同复制书稿。

 

 

#include <cstdio>#include <algorithm>#include <string>using std::max;long n,k;long a[100010];bool can(long mid){long bsum = 0;long block = 0;for (long i=1;i<n+1;i++){bsum += a[i];if (bsum > mid){bsum = a[i];block ++;if (block == k)return false;}}if (block <= k-1 && bsum <= mid)return true;elsereturn false;}long getint(){long rs=0;bool sgn=1;char tmp;do tmp=getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp=='-'){tmp=getchar();sgn=1;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}int main(){freopen("seq.in","r",stdin);freopen("seq.out","w",stdout);n = getint();k = getint();long sum = 0;long maxa = -0x7f7f7f7f;for (long i=1;i<n+1;i++){a[i] = getint();maxa = max(maxa,a[i]);sum += a[i];}long l = maxa;long r = sum;long ans = 0x7f7f7f7f;while (l <= r){long mid = (l+r)>>1;if (can(mid)){if (mid < ans)ans = mid;r = mid-1;}elsel = mid+1;}printf("%ld",ans);return 0;}


 

原创粉丝点击