1. 程式人生 > >UVa 714 Copying Books——二分最大值最小化

UVa 714 Copying Books——二分最大值最小化

注意上界在累加時可能超過int範圍

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int m, k;
long long a[1000];

bool judge(long long x) {
    long long sum = 0, cnt = 1;
    for (int i = m; i >= 1; i--) {
        sum += a[i];
        if (sum > x) {
            sum = a[i];
            cnt++;
            if (cnt > k) return false;
        }
    }
    return true;
}

void output(int ans) {
    int gang[1000];
    memset(gang, 0, sizeof(gang));
    long long sum = 0, cnt = 1;
    for (int i = m; i >= 1; i--) {
        sum += a[i];
        if (sum > ans) {
            sum = a[i];
            cnt++;
            gang[i] = 1;
        }
        if (k - cnt == i) {
            for (; i >= 1; i--) {
                gang[i] = 1;
            }
            break;
        }
    }
    int flag = 0;
    for (int i = 1; i <= m; i++) {
        if (flag++) printf(" ");
        printf("%d", a[i]);
        if (gang[i]) printf(" /");
    }
    printf("\n");
}

int main()
{
    int T; scanf("%d", &T);
    while (scanf("%d %d", &m, &k) == 2) {
        long long L = 0, R = 0;
        for (int i = 1; i <= m; i++) {
            scanf("%lld", &a[i]);
            R += a[i];
            if (a[i] > L) L = a[i];
        }
        while (L <= R) {
            long long x = L + (R - L) / 2;
            if (judge(x)) R = x - 1;
            else L = x + 1;
        }
        output(L);
    }
    return 0;
}