In **ordered** sets and maps, the entries are sorted in order of key. Insertions, deletions, and searches are all $O(\log N)$, where $N$ is the number of elements in the set or map, but accessing or removing the next key higher or lower than some input $k$ is also supported.
As well as those supported by `unordered_set`, the ordered set also allows four additional operations: `begin()`, which returns an iterator to the lowest element in the set, `end()`, which returns an iterator to the highest element in the set, `lower_bound`, which returns an iterator to the least element greater than or equal to some element `k`, and `upper_bound`, which returns an iterator to the least element strictly greater than some element `k`.
The primary limitation of the ordered set is that we can't efficiently access the $k^{th}$ largest element in the set, or find the number of elements in the set greater than some arbitrary $x$. These operations can be handled using a data structure called an order statistic tree (see Gold - Binary Indexed Trees).
### Java
As well as those supported by the unordered set, the ordered set also allows four additional operations: `first`, which returns the lowest element in the set, `last`, which returns the highest element in the set, `lower`, which returns the greatest element strictly less than some element, and `higher`, which returns the least element strictly greater than it.
```java
TreeSet<Integer> set = new TreeSet<Integer>();
set.add(1); // [1]
set.add(14); // [1, 14]
set.add(9); // [1, 9, 14]
set.add(2); // [1, 2, 9, 14]
System.out.println(set.higher(7)); // 9
System.out.println(set.higher(9)); // 14
System.out.println(set.lower(5)); // 2
System.out.println(set.first()); // 1
System.out.println(set.last()); // 14
set.remove(set.higher(6)); // [1, 2, 14]
System.out.println(set.higher(23); // ERROR, no such element exists
```
## Ordered Maps
### C++
The ordered map supports all of the operations that an unordered map supports, and additionally supports `lower_bound` and `upper_bound`, returning the iterator pointing to the lowest entry not less than the specified key, and the iterator pointing to the lowest entry strictly greater than the specified key respectively.
The ordered map supports all of the operations that an unordered map supports, and additionally supports `firstKey` / `firstEntry` and `lastKey` /` lastEntry`, returning the lowest key/entry and the highest key/entry, as well as `higherKey` /` higherEntry` and `lowerKey` / `lowerEntry`, returning the lowest key/entry strictly higher than the specified key, or the highest key/entry strictly lower than the specified key.
```java
TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
In addition to all of the regular set operations, the multiset `count()` method returns the number of times an element is present in the multiset. However, this method takes time **linear** in the number of matches so you shouldn't use it in a contest.
The `begin()`, `end()`, `lower_bound()`, and `upper_bound()` operations work the same way they do in the normal sorted set.
**Warning:** If you want to remove a value *once*, make sure to use `multiset.erase(multiset.find(val))` rather than `multiset.erase(val)`. The latter will remove *all* instances of `val`.
```cpp
multiset<int> ms;
ms.insert(1); // [1]
ms.insert(14); // [1, 14]
ms.insert(9); // [1, 9, 14]
ms.insert(2); // [1, 2, 9, 14]
ms.insert(9); // [1, 2, 9, 9, 14]
ms.insert(9); // [1, 2, 9, 9, 9, 14]
cout << ms.count(4) << '\n'; // 0
cout << ms.count(9) << '\n'; // 3
cout << ms.count(14) << '\n'; // 1
ms.erase(ms.find(9));
cout << ms.count(9) << '\n'; // 2
ms.erase(9);
cout << ms.count(9) << '\n'; // 0
```
### Java
While there is no `Multiset` in Java, we can implement one using the `TreeMap` from values to their respective frequencies. We declare the `TreeMap` implementation globally so that we can write functions for adding and removing elements from it.
```java
static TreeMap<Integer, Integer> multiset = new TreeMap<Integer, Integer>();
public static void main(String[] args){
...
}
static void add(int x){
if(multiset.containsKey(x)){
multiset.put(x, multiset.get(x) + 1);
} else {
multiset.put(x, 1);
}
}
static void remove(int x){
multiset.put(x, multiset.get(x) - 1);
if(multiset.get(x) == 0){
multiset.remove(x);
}
}
```
The first, last, higher, and lower operations still function as intended; just use `firstKey`, `lastKey`, `higherKey`, and `lowerKey` respectively.
## Standard
Do roughly the first half of the Sorting and Searching section in the [CSES Problem Set](https://cses.fi/problemset/).