タイトルを取得するのは簡単\(\ N-)と\(Kを\) 2点のみによって、対象を列挙するように、単調に二分性質を満たす(\ N-)\をそれぞれに、その後、\(\ N-)その対応するシミュレート\(K \)を詳細にコード注意を注意し、次に、いつ現在の\(K \)対象の要件に等しい\(K \)すべてのケースを見つけるために、二つの点に、それぞれ、左右、 。
#include <bits/stdc++.h>
#define N 3000011
#define int long long
using namespace std;
int n, k, x[N], sum[N], maxn, minn = 2147483647124544;
int check(int mid)
{
int l = 1, now = 0, tot = 0;
while (l <= n)//这里是不能二分的,因为不满足二分单调性。
{
while (now < mid && l <= n)
{
now += x[l++];
now = max(now, 0LL);
}
if (now >= mid)
tot++, now = 0;//此处l不能++, 因为循环里已经++了
}
return tot;
}
signed main()
{
scanf("%lld%lld", &n, &k);
for (int i = 1; i <= n; i++)
{
scanf("%lld", &x[i]);
sum[i] = sum[i - 1] + x[i];
if (sum[i] < 0) sum[i] = 0;
}
// printf("%lld ", check(3));
int l = 1LL, r = 1000000000000LL;//二分n
while (l <= r)
{
int mid = (l + r) >> 1;
if (check(mid) > k)//如果最终的结果比k大,n越大,k越小
l = mid + 1;
if (check(mid) < k)
r = mid - 1;
if (check(mid) == k)
{
minn = min(minn, mid), maxn = max(maxn, mid);
r = mid - 1;
}
}
l = 1LL, r = 1000000000000LL;
while (l <= r)
{
int mid = (l + r) >> 1;
if (check(mid) > k)//如果最终的结果比k大,n越大,k越小
l = mid + 1;
if (check(mid) < k)
r = mid - 1;
if (check(mid) == k)
{
minn = min(minn, mid), maxn = max(maxn, mid);
l = mid + 1;
}
}
if (minn == 2147483647124544)
printf("-1"), exit(0);
printf("%lld %lld", minn, maxn);
return 0;
}