cppAcademy
FROM LEARNING TO COMPETING

Real problems.
Your next challenge.

Explore the Group C Olympiad and Autumn Tournament archive.
Choose a topic. Find a challenge. Build your solution.

274 tasks: 213 from the Municipal, Regional, and National Olympiad rounds (2009–2026), 57 Autumn Tournament tasks (2007–2025), and 4 previously featured problems. 207 tasks have independently written English summaries, analyses, and C++17 solutions; the remaining entries link to Arena. Difficulty labels are learning estimates, not official ratings. Special formats and source clarifications are explained on affected tasks.
GROUP C2020 · MediumBinary search on the answer

Partition the Popcorn Packages

Autumn Tournament (2020)

Submission name: popcorn.cpp

Problem summary

N packages lie in a fixed order. Distribute them among K people so each person receives one contiguous group, possibly empty, and every package is assigned whole. Each person eats S popcorns per second. Minimize the integer number of seconds until everyone has finished.

Input

N K S, followed by N positive package sizes.

Output

The minimum completion time, rounded up to whole seconds.

Constraints

1 ≤ N,K ≤100000; 1 ≤ S ≤50; 1 ≤ package size ≤10000.

Worked example

Original statement sample.

Input

5 3 4
5 8 3 10 7

Output

4

Solution analysis

  1. If everyone must finish within t whole seconds, each person can receive at most t·S popcorns. Check this capacity greedily: keep adding packages to the current group until the next one would exceed it, then start a new group. A package larger than the capacity makes t impossible.
  2. The greedy check produces the minimum number of groups for this capacity: ending a group earlier cannot allow its successor to begin later. If at most K groups suffice, unused people receive empty groups. Feasibility is monotone because extra time only increases the capacity, so binary-search the first feasible t.
  3. For the sample, t=3 gives capacity 12 and needs groups[5],[8,3],[10],[7], more than three people. At t=4, capacity 16 permits[5,8,3],[10],[7], so the minimum is 4.

Why it works

Greedy always takes the longest prefix that can fit in each group. After any fixed number of groups, no other valid partition can have consumed a longer prefix; this follows inductively by comparing group endpoints. Thus its group count is minimal. Binary search returns the smallest capacity-time passing this exact feasibility test.

Complexity: O(N log(sum P +1)) time and O(N) memory. Each feasibility test scans the packages once, and binary search halves a bounded interval of possible seconds.

Watch out. Do not reorder packages or split one package between people. Use ceiling division for time bounds and long long for sums and capacity multiplication. K may exceed N because empty groups are allowed.

Commented C++17 solution

An independently written complete program with standard headers.

#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    int people;
    long long speed;
    cin>>n>>people>>speed;
    vector<int>packages(n);
    long long total=0;
    int largest=0;
    for(int&amount:packages){
        cin>>amount;
        total+=amount;
        largest=max(largest,amount);
    }
    // Greedy groups test whether everyone can finish within this time.
    auto possible=[&](long long seconds){
        long long capacity=seconds*speed;
        long long current=0;
        int groups=1;
        for(int amount:packages){
            if(amount>capacity){
                return false;
            }
            if(current+amount>capacity){
                groups++;
                current=0;
            }
            current+=amount;
        }
        return groups<=people;
    };
    long long low=(largest+speed-1)/speed;
    long long high=(total+speed-1)/speed;
    while(low<high){
        long long middle=low+(high-low)/2;
        if(possible(middle)){
            high=middle;
        }
        else{
            low=middle+1;
        }
    }
    cout<<low<<'\n';
}

Source: Arena Olimpiici ↗