P1182 数列分段 Section II

P1182 数列分段 Section II

提交 34.77k
通过 11.79k
时间限制 1.00s
内存限制 125.00MB
题目提供者 洛谷
历史分数100

提交记录

标签

 
查看算法标签
进入讨论版

相关讨论

 
查看讨论

推荐题目

 
查看推荐
 

展开

题目描述

对于给定的一个长度为N的正整数数列 A1∼NA_{1\sim N}A1N,现要将其分成 MMM(M≤NM\leq NMN)段,并要求每段连续,且每段和的最大值最小。

关于最大值最小:

例如一数列 4 2 4 5 14\ 2\ 4\ 5\ 14 2 4 5 1 要分成 333 段。

将其如下分段:

[4 2][4 5][1][4\ 2][4\ 5][1] [4 2][4 5][1]

第一段和为 666,第 222 段和为 999,第 333 段和为 111,和最大值为 999。

将其如下分段:

[4][2 4][5 1][4][2\ 4][5\ 1] [4][2 4][5 1]

第一段和为 444,第 222 段和为 666,第 333 段和为 666,和最大值为 666。

并且无论如何分段,最大值不会小于 666。

所以可以得到要将数列 4 2 4 5 14\ 2\ 4\ 5\ 14 2 4 5 1 要分成 333 段,每段和的最大值最小为 666。

输入格式

111 行包含两个正整数 N,MN,MN,M。

222 行包含 NNN 个空格隔开的非负整数 AiA_iAi,含义如题目所述。

输出格式

一个正整数,即每段和最大值最小为多少。

输入输出样例

输入 #1
5 3
4 2 4 5 1
输出 #1
6

 

 

思路

  要求最大值最小,二分即可。因为要求段的最大值所以在 max a[i] ~ sum a[i] 中二分答案。

  如果在 1 ~ sum a[i] 中二分会WA4,调了半个多小时不知道为什么,翻了翻题解也没人解释。。。

 

CODE

 1 #include <bits/stdc++.h>
 2 #define dbg(x) cout << #x << "=" << x << endl
 3 #define eps 1e-8
 4 #define pi acos(-1.0)
 5 
 6 using namespace std;
 7 typedef long long LL;
 8 
 9 template<class T>inline void read(T &res)
10 {
11     char c;T flag=1;
12     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
13     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
14 }
15 
16 namespace _buff {
17     const size_t BUFF = 1 << 19;
18     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
19     char getc() {
20         if (ib == ie) {
21             ib = ibuf;
22             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
23         }
24         return ib == ie ? -1 : *ib++;
25     }
26 }
27 
28 int qread() {
29     using namespace _buff;
30     int ret = 0;
31     bool pos = true;
32     char c = getc();
33     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
34         assert(~c);
35     }
36     if (c == '-') {
37         pos = false;
38         c = getc();
39     }
40     for (; c >= '0' && c <= '9'; c = getc()) {
41         ret = (ret << 3) + (ret << 1) + (c ^ 48);
42     }
43     return pos ? ret : -ret;
44 }
45 
46 const int maxn = 1e5 + 7;
47 
48 int n,k;
49 int a[maxn];
50 int ans;
51 int maxx;
52 
53 inline bool check(int x) {
54     int tot = 0, cnt = 0;
55     for ( int i = 1; i <= n; ++i ) {
56         if(tot + a[i] <= x) {
57             tot += a[i];
58         }
59         else {
60             tot = a[i];
61             cnt++;
62         }
63     }
64     if(cnt >= k) {
65         return true;
66     }
67     return false;
68 }
69 
70 int main()
71 {
72     int l = 0, r = 0, mid;
73 
74     scanf("%d %d",&n, &k);
75     for ( int i = 1; i <= n; ++i ) {
76         scanf("%d",&a[i]);
77         l = max(l, a[i]);
78         r += a[i];
79     }
80     //l = 1, r = 1e9;
81     mid = (l + r) >> 1;
82     while( l <= r) {
83         mid = (l + r) >> 1;
84         if(check(mid)) {
85             l = mid + 1;
86         }
87         else {
88             r = mid - 1;
89         }
90     }
91     printf("%d\n",l);
92     return 0;
93 }
View Code

 

posted @ 2020-02-18 21:53  Orangeko  阅读(220)  评论(0编辑  收藏  举报