Lesson 26 of 50 intermediate

Using sort() and Built-in Tools

Let C++ do the heavy sorting for you

Open interactive version (quiz + challenge)

Real-world analogy

sort() is like having a magic wand that organizes anything instantly. Instead of manually comparing and swapping elements yourself (like in bubble sort), you wave the wand and everything falls into perfect order. It is not just faster to type — it is actually faster to run, using a clever algorithm called IntroSort behind the scenes.

What is it?

C++ provides powerful built-in sorting and searching tools that every competitive programmer must know. The sort() function sorts data in O(n log n) time, while lower_bound and upper_bound perform binary searches on sorted data in O(log n). Mastering these tools means you spend less time writing code and more time solving problems.

Real-world relevance

Every app you use relies on sorting: your email inbox sorted by date, your music playlist sorted by artist, search results sorted by relevance, leaderboards sorted by score. The fast sorting algorithms behind sort() (like QuickSort and MergeSort) were invented decades ago and are still the backbone of every modern system.

Key points

Code example

#include <bits/stdc++.h>
using namespace std;

bool descending(int a, int b) {
    return a > b; // Returns true if a should come before b
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    // Sort a vector
    vector<int> v = {5, 2, 8, 1, 9, 2, 8, 3};
    sort(v.begin(), v.end());
    cout << "Ascending: ";
    for (int x : v) cout << x << " ";
    cout << "\n";

    // Sort descending
    sort(v.begin(), v.end(), descending);
    cout << "Descending: ";
    for (int x : v) cout << x << " ";
    cout << "\n";

    // Sort ascending again for binary search
    sort(v.begin(), v.end());

    // lower_bound and upper_bound
    auto lo = lower_bound(v.begin(), v.end(), 2);
    auto hi = upper_bound(v.begin(), v.end(), 2);
    cout << "First 2 at index: " << (lo - v.begin()) << "\n";
    cout << "Count of 2s: " << (hi - lo) << "\n";

    // Sorting pairs
    vector<pair<int,int>> scores = {{90, 1}, {85, 3}, {90, 2}};
    sort(scores.begin(), scores.end());
    cout << "Sorted pairs: ";
    for (auto p : scores) cout << "(" << p.first << "," << p.second << ") ";
    cout << "\n";

    return 0;
}

Line-by-line walkthrough

  1. 1. sort(v.begin(), v.end()); — this sorts the entire vector v in ascending order. begin() points to the first element and end() points just past the last element. This range notation is standard in C++ STL.
  2. 2. sort(v.begin(), v.end(), descending); — here we pass our custom comparison function. It tells sort() that a should come before b when a > b, resulting in descending order.
  3. 3. auto lo = lower_bound(v.begin(), v.end(), 2); — lower_bound uses binary search to find the first element >= 2. The 'auto' keyword lets C++ figure out the iterator type for us.
  4. 4. auto hi = upper_bound(v.begin(), v.end(), 2); — upper_bound finds the first element > 2. The elements between lo and hi are all equal to 2.
  5. 5. (hi - lo) — subtracting two iterators gives the number of elements between them. This tells us how many times 2 appears in the sorted vector.
  6. 6. vector> scores — pairs are sorted by first element, then second. So (85,3) comes before (90,1), and (90,1) comes before (90,2).

Spot the bug

#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> v = {5, 3, 1, 4, 2};

    // Find the value 3 using lower_bound
    auto it = lower_bound(v.begin(), v.end(), 3);
    if (it != v.end() && *it == 3) {
        cout << "Found 3 at index " << (it - v.begin()) << "\n";
    } else {
        cout << "3 not found\n";
    }

    return 0;
}
Need a hint?
lower_bound uses binary search. What is the one requirement for binary search to work correctly?
Show answer
The bug is that the vector is not sorted! lower_bound requires sorted data because it uses binary search internally. Without sorting, it may look in the wrong half and miss the element entirely. Fix: add sort(v.begin(), v.end()); before calling lower_bound.

Explain like I'm 5

Instead of sorting things by hand (which is slow and tiring), C++ gives you a magic command called sort() that does it for you, super fast. It is like asking a super-smart robot to organize your toys by size — the robot knows the fastest tricks and does it in seconds, even if you have millions of toys. You can even tell the robot 'sort biggest first!' or 'sort by color then by size!' It is your ultimate sorting tool.

Fun fact

The C++ sort() function is required by the language standard to run in O(n log n) in the worst case. Most implementations use IntroSort, invented by David Musser in 1997. It starts with QuickSort (fast on average), switches to HeapSort if recursion gets too deep (to guarantee O(n log n) worst case), and uses InsertionSort for tiny sub-arrays (because it is faster for small sizes). It is an engineering masterpiece!

Hands-on challenge

Read n numbers, sort them, then answer q queries. Each query gives a number x — print how many times x appears in the array using lower_bound and upper_bound. Test with array [1, 2, 2, 3, 3, 3, 4, 5] and queries for 3 (answer: 3), 2 (answer: 2), and 6 (answer: 0).

More resources

Open interactive version (quiz + challenge) ← Back to course: CP Zero to Hero