Solving Problems with std::sort()
There are many problems (either programming challenges or mathematical pizzles) that have an effiecient solution when the data are listed and stored in order. In this subsection, we introduce three ad-hoc simple exmaples where there are elegant solutions with sorting.
Problems Become Easier To Solve After Sorting
Exmaple: [CF1248B] Grow The Tree
Short Description
You are given sticks, each of them has length . The goal is to connect all the sticks, with each touching sticks perpendicular to each other, in arbitrary order. What is the longest possible squared Euclidean distance from some stick endpoint to another stick endpoint?
Solution
We know that given the constraint, there can only be two perpendicular directions for the sticks. Furthermore, there are exactly sticks with one direction and sticks with another directrion. Thus, our goal is to partition these sticks into two groups.
Let the total length of sticks in group 1 to be and the total length of the sticks in group2 to be . Then the farthest squared Euclidean distance among the endpoints of the sticks, are . Notice that we have total stick length . In order to maximize this distance, we should make one of or as large as possible. Hence, there are at most two possible cases to consider: either or . Our algorithm then return one of the larger distance.
Follow-Up
Actually we do not have to sort the entire array in order to split the values into two groups.
This is just a selection problem (wiki), so using std::nth_element() might help. However, the implementation will become more complex and it is not recommended in competitive programming unless the time constraints are tight.
Customize Your Sort
Sometimes you can pass in your custom comparator to the sorting function.
Example: [CF1312B] Bogosort
Shortest Description
You would like to shuffle a given array such that for any we have . Output any valid shuffled array.
Solution
If we sorted the array in decreasing order, then whenever , we have . Therefore, we are able to solve the problem by just sorting the array in decreasing order.
Example: [CF632C] The Smallest String Concatenation
Short Description
You are given a list of strings . You'd like to concatenate them together in some order such that the resulting string would be lexicographically smallest.
Solution
A lexicographically smallest answer corresponds to a permutation of the given strings.
If we interchange the neighboring strings on an answer, it shoudn't give us a better concatenated string.
Hence, we can define our operator < on any two strings by testing which order gives a smaller lexicographical order. In fact, we can show that this operator is transitive. That is, for any three strings , as long as and we have . The transitivity and the comparability gives us an totol order to the entire sequence, thus we are able to sort all strings using our customized comparator.
If we have an sorted array, then searching for a specific key arises as a natural and important question. The most common algorithm that searches for a key in a sorted array is through binary search.
However, a correct implementation of a binary search could sometimes become very challenging. Fortunately we have std::lower_bound() and std::upper_bound() functions provided by C++ standard library.