题目
点我点我点我点我点我点我点我点我点我点我点我点我点我点我点我点我
题解
本题解法:
二分答案+贪心
思路:
首先,分析题目,求最大值的最小化,直接联想到二分,So我们直接二分答案,关键是要怎么去高效的check,因为大家很容想到前缀和,但实际上这个空间是可以省略的,为什么呢?我们考虑一个贪心的思路,能加的就加上,不能则新开一段,so对于二分的值x,我们从数列a从前往后扫,如果tot大于了x,我们不加而是tot重新赋值并且num++,最后只需判断num是否不小于m就行了。这样判断与前缀和一样是O(n)的复杂度,但是节省了空间。虽然实际上毫无卵用
code
#include <bits/stdc++.h>
#define MAXX 101000
#define ll long long
using namespace std;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') w = -1; ch = getchar(); }
while(isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
return s * w;
}
int n, m;
int righ, lef, mid, cnt = 0, tot = 0;
int a[MAXX];
inline bool check(int x) {
for (int i = 1; i <= n; ++i) {
if (tot + a[i] <= x) tot += a[i];
else {
tot = a[i];
cnt++;
}
}
return cnt >= m;
}
int main() {
n = read(); m = read();
for (int i = 1; i <= n; ++i) {
a[i] = read();
righ += a[i];
lef = max(lef, a[i]);
}
while (lef <= righ) {
mid = (lef + righ) >> 1;
tot = 0, cnt = 0;
if (check(mid)) lef = mid + 1;
else righ = mid - 1;
}
printf("%d\n", lef);
return 0;
}