cppAcademy
FROM LEARNING TO COMPETING

Real problems.
Your next challenge.

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

213 tasks across the Municipal, Regional, and National rounds (2009–2026), plus 4 previously featured problems. 146 tasks have independently written English summaries, analyses, and C++17 solutions; the remaining entries link to Arena. Topic tags are from Arena or our reviewed explanations. Difficulty labels are learning estimates, not official ratings.
GROUP C2025 · MediumSorting Greedy

Chain Orders

National Olympiad — Municipal round

Submission name: storage.cpp

Problem summary

Fulfil N chain orders of lengths Lᵢ. One opened link can detach an ordered chain from the spool and leave one loose opened link. Loose links can be assembled into other ordered chains without additional openings. Find the minimum openings, allowing any order of processing.

Input

N and the N lengths.

Output

The minimum number of opened links.

Constraints

1 ≤ N ≤ 100,000; 1 ≤ Lᵢ ≤ 100,000.

Worked example

An independently prepared example for this explanation.

Input

4
1 1 8 9

Output

2

Solution analysis

  1. If t orders are assembled from loose links, N−t spool operations can supply N−t links.
  2. Choose the t shortest orders. Find the largest t whose total length is at most N−t.

Why it works

Any selection of t assembled orders needs at least the sum of the t shortest lengths. Conversely those orders can be assembled after executing the remaining spool orders, so the inequality is both necessary and sufficient.

Complexity: O(N log N) time, O(N) space.

Watch out. Loose links are already opened, so joining them needs no further opening operation.

Commented C++17 solution

An independently written complete program with standard headers.

// Key idea: Any selection of t assembled orders needs at least the sum of the t shortest lengths.
// Conversely those orders can be assembled after executing the remaining spool orders, so the
// inequality is both necessary and sufficient.
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
    int n;
    cin>>n;
    vector<int>a(n);
    for(int&x:a){
        cin>>x;
    }
    sort(a.begin(),a.end());
    long long sum=0;
    int t=0;
    while(t<n&&sum+a[t]<=n-t-1){
        sum+=a[t++];
    }
    cout<<n-t<<'\n';
}

Source: Arena Olimpiici ↗