羅区P4343 [SHOI2015】自動ブラシ機問題

タイトル

タイトルを取得するのは簡単\(\ 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;
}   

おすすめ

転載: www.cnblogs.com/liuwenyao/p/11715574.html