Hướng dẫn giải của Chia hành lý


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

subtask 1:

đầu tiên, chúng ta phải thử xây dựng 1 hàm, kiểm tra xem từ ~n~ món hàng có thể chia ra ~k~ nhóm hàng có giá trị là tối đa là ~val~ hay không

ll cal(ll val){
    ll segs=1;// tính số đoạn đã chia được 
    ll s=0;// tính tổng của từng đoạn con 
    for(int i=0;i<n;i++){
        if(a[i]>val){
            return k+1;// trường hợp a[i] lớn hơn val thì max của mảng không nằm ở đây nữa, có thể return số lớn hơn k và trở về ngay
        }
        if(s+a[i]<=val){
            s+=a[i];
        }
        else s=a[i],segs++;
    }

    return segs;
    // nếu số đoạn tính được từ n món hàng
}

với cách kiểm tra trên, mỗi lần kiểm tra ta tốn dpt là o(n), n=10^5

dễ nhận thấy đây là hàm nghiêm nghặt tăng theo giá trị val -> có thể áp dụng chặt nhị phân

subtask 2:

ta chặt nhị phân tìm cận dưới của hàm cal, ta không thể duyệt thử tất cả trường hợp với val từ 1->10^18 vì giá trị vì giá trị của ~cal~ có thể rất lớn. vì sẽ có tận 10^18 trường hợp thử, nhân với dpt với mỗi lần thử, ta có được dpt là 10^5*10^18 = 10^23 -> quá mức tính toán của máy chấm trong 1s. máy chấm chỉ tính được khoảng 10^8 phép tính / giây -> cần tốn khoảng 30 triệu năm để tính toán xong dược.

nếu áp dụng chặt nhị phân ta giảm xuống dpt còn n * log2(10^18) = 60n -> phù hợp với yêu cầu của bài toán.

ll bs_lower_bound() {
    ll l = 0;
    ll h = 1e18;
    while (l < h) {
        ll mid =  l + (h - l) / 2;
        if (cal(mid)<=k) {
            h = mid;
        } else {
            l = mid + 1;


        }
    }
    return l;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.