CPP STL
CPP STL
Programming in C++
David Wai {wjx}
2025-02-15
Programming in C++ 2
Why C++?
● C++ shares similar syntax with many other programming languages
○ Java, JavaScript, C#, Objective C, PHP, etc.
C++ Standard
Starting from 2011, 3 years a standard (C++11, C++14, …)
● C++23 has been published, and work is now underway on C++26
● In most cases, new standards are backward compatible
○ There are some special cases like gets and random_shuffle
● g++ compilation flag: -std=c++11, -std=c++14, …
Different contests and online judges may support different standards
● Codeforces supports C++23
● HKOI Online Judge supports C++20
● IOI, APIO supports C++17
● NOI, EGOI supports C++14
● Be careful about the supported version as some functions may be in new
standard, check the compilation flags if you are not sure about it
Programming in C++ 6
int main() {
Example without
std::cout << "Hello, World!" << std::endl; using namespace std;
return 0;
}
Programming in C++ 10
Integers
int: 32 bits in most systems
long long: 64 bits in most systems
__int128 is also supported in most modern compilers (no input / output functions)
16
Programming in C++ 17
Arithmetic operators
name syntax name syntax To change the variable itself, you may
also use a += b, a -= b, …
addition a + b bitwise not ~a
Division
In C++, we use / for both integer division and floating point division
If both dividend and divisor are integer types, integer division is performed
If any of the dividend and divisor is a floating point type, floating point division is performed
2
cout << 5 / 2 << '\n'; 2.5
2.5
cout << 5.0 / 2 << '\n';
cout << 5 / 2.0 << '\n';
return 0;
}
19
Programming in C++ 20
20
Programming in C++ 21
Characters
A 8-bit integer type
You can do arithmetic directly on it
In C++, we use single quote for characters and double quote for strings
int main() { Input Output
char c = 'A';
A
cout << c << '\n'; a
c += 32; 0
cout << c << '\n'; 4
c = 48;
cout << c << '\n';
cout << 'E' - 'A' << '\n';
return 0;
}
21
Programming in C++ 22
Boolean
Only 2 values: true and false
Logical operators:
name syntax
negation !a // not a
inclusive or a || b // a or b
Programming in C++ 23
Comparison operators
Compare two variables, return bool
If statement
You can omit the bracket if there is only one statement
24
Programming in C++ 25
For loop
Syntax: for (initial; condition; step)
You can omit the bracket if there is only one statement
1
for (int i = 1; i <= 5; ++i) { 2
3
cout << i << '\n'; 4
5
}
return 0;
}
25
Programming in C++ 26
Arrays
We can use a character array to store strings
26
Programming in C++ 27
Pointers
Pointer stores the address of another variable
Use * to dereference the pointer
Use & to get the address of a variable
int main() { Input Output
int a = 1; 2
int* p = &a;
*p = 2;
cout << a << '\n';
return 0;
}
27
Programming in C++ 28
C++ array
With the exception of const arrays, (e.g. const char s[])
modern C++ discourages the use of raw arrays
The type and size of an array is fixed once declared
array<int, 10> a; Input Output
28
Programming in C++ 29
C++ array
Arrays can also be declared with initialization
The size and type will be automatically determined (class template argument
deduction, since C++17). Here, the type of a is array<int, 3>
array a{4, 8, 3}; Input Output
int main() { 15
cout << a[0] + a[1] + a[2] << '\n';
return 0;
}
29
Programming in C++ 30
C++ STL
C++ Standard Template Library
Iterator
A generalization of pointer
Similar to pointers, can use *it to dereference
Iterator
To increment it by n elements:
● advance(it, n)
○ O(n) in general
○ O(1) if it is a random access iterator
To get the next iterator (since C++11):
● next(it)
To get the previous iterator (since C++11):
● prev(it)
Programming in C++ 38
Vector iterators
To get the iterator pointing to the first element of the vector:
● [Link]()
To get the iterator pointing to the element after the last element of the vector:
● [Link]()
There are also reverse iterators, which can be used to iterate through the
vector in reverse order
● [Link](): the iterator pointing to the last element of the vector
● [Link](): the iterator pointing to the element before the first element of
the vector
Programming in C++ 39
Vector
To iterate through the whole vector:
● Use an index:
○ for (int i = 0; i < [Link](); i++)
○ Access the value using a[i]
● Use a iterator:
○ for (auto it = [Link](); it != [Link](); it++)
○ Access the value using *it
● Use range-based for loop (since C++11):
○ for (auto v : a) (pass by value)
○ for (auto& v : a) (pass by reference)
○ Access the value using v
Programming in C++ 40
Vector
vector<int> a; Output
for (int i = 0; i < 10; i++) a.emplace_back(10 - i);
for (auto x : a) cout << x << ' '; 10 9 8 7 6 5 4 3 2 1
cout << '\n'; 1
cout << [Link]() << '\n'; 9
a.pop_back();
10 9 8 7 6 5 4 3 2
cout << [Link]() << '\n';
5 5 5 5 5 5 5 5 5
for (int i = 0; i < [Link](); i++) cout << a[i] << ' ';
cout << '\n';
for (auto& x : a) x = 5;
for (auto it = [Link](); it != [Link](); it++) cout << *it << ' ';
cout << '\n';
Programming in C++ 41
Vector efficiency
The size of a vector is dynamic, how to ensure it does not take too much time
compared to an array?
The main idea is reallocation
When the vector is full, a larger memory space will be allocated (usually with
double size)
Everything in the old space will then be moved to the new space
Programming in C++ 42
Vector efficiency
vector<int> a; Output
for (int i = 0; i < 10; i++) {
a.emplace_back(i); size: 1 capacity: 1
cout << "size: " << [Link]() << " capacity: " << [Link]() << size: 2 capacity: 2
'\n'; size: 3 capacity: 4
} size: 4 capacity: 4
size: 5 capacity: 8
The allocated size of a vector can be queried by size: 6 capacity: 8
using [Link]() size: 7 capacity: 8
size: 8 capacity: 8
size: 9 capacity: 16
size: 10 capacity: 16
Programming in C++ 43
Vector efficiency
Assume that you call push_back() n times.
The total cost comprises of:
● Cost of adding an element
○ 1 operation per push_back
○ Total n operations for n push_back
● Cost of moving elements when vector is full
○ 1, 2, 4, 8, …, 2k (where 2k < n)
○ The sum of above = 2k+1 - 1 < 2n
Total cost for n push_back = n + (<2n) < 3n, and therefore is O(n)
We can say that push_back is amortized O(1)
Programming in C++ 44
Vector efficiency
If you know the expected maximum size of the vector
● use reserve() to preallocate the memory space so reallocate is not
needed
If you just want to use it like a fix-sized array
● Use constructor when declaring the vector
● Use resize() to set the size of the vector
Programming in C++ 45
String
Defined in header <string>
C++ strings are very easy to use
Similar to vector
● You can also use ranged-based for loop to iterate over a string
● You can get iterators from string to perform operations
You can concatenate strings together using the + operator
You can compare strings directly using comparison operators
● You can also use compare(), which returns 0 when the strings are equal,
negative number when the left string is smaller, and positive otherwise
Programming in C++ 47
Using string::iterator
string s = "abcdef"; Output
for (auto it = [Link](); it != [Link](); ++it) cout << *it << '\n';
reverse([Link](), [Link]()); a
cout << s << '\n'; b
c
d
e
f
fedcba
Programming in C++ 49
Concatenate strings
string s = "ab"; Output
string t = "d";
s += 'c'; // append a character 3
t += "ef"; // append a string abcdef
cout << [Link]() << '\n';
cout << s + t << '\n';
Programming in C++ 50
Compare strings
cout << ("abc"s == "abc"s) << '\n'; Output
cout << ("abc"s < "def"s) << '\n';
cout << ("abcd"s > "abc"s) << '\n'; 1
cout << "abc"[Link]("abx") << '\n'; 1
cout << "xyz"[Link]("xyz") << '\n'; 1
cout << "def"[Link]("a") << '\n';
-21
It 0can be any negative integer
3
Find string
string s = "This is a string"; Output
int n = [Link]("is");
cout << n << '\n'; 2
n = [Link]("is", 5); 5
cout << n << '\n'; -1
n = [Link]('q');
18446744073709551615
cout << n << '\n';
cout << string::npos << '\n';
Programming in C++ 53
Modify string
string s = "abc"; Output
[Link](1, "abc", 2);
cout << s << '\n'; aabbc
[Link](3); aab
cout << s << '\n'; a123b
[Link](1, 1, "123");
cout << s << '\n';
Programming in C++ 54
Get substring
string s = "[Link] Output
cout << [Link](14, 4) << '\n';
cout << [Link](8) << '\n'; hkoi
[Link]
Programming in C++ 55
Functions
Functions with return type should have a return statement
Void functions can omit the return statement
57
Programming in C++ 58
Early return
If you have a return statement at the end of a if block, no need to add else
58
Programming in C++ 59
Pass by reference
Pass by reference makes the identifier refer to the same variable specified in
the argument. Therefore, the value can be changed inside the function
Value 1
59
Programming in C++ 60
60
Programming in C++ 61
Recursion
int fib(int n) { Output
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2); 610
}
int main() {
cout << fib(15) << '\n';
return 0;
}
Programming in C++ 62
Lambda expression
An unnamed function object
Can be declared inside a function, or even inside a lambda expression (nested
lambdas)
Other than behave like a normal function (takes parameters), it can also
capture variables
Syntax: [ captures ] ( parameters ) { body }
Capture list (see cppreference for more details):
● =: pass by value
● &: pass by reference
Programming in C++ 63
Lambda expression
auto sum = [](int a, int b) { return a + b; }; Output
cout << sum(1, 2) << '\n';
auto generic_sum = [](auto a, auto b) { return a + b; }; 3
cout << generic_sum(1.2, 3.4) << '\n'; 4.6
Recursive lambda
Lambdas are unnamed function objects, so there is no name for us to call itself
recursively
Is it possible to recursively call it?
Two workarounds:
● Declare a variable by using function first
● Pass itself as a parameter
Programming in C++ 65
Template
There are many types of templates in C++
● Class template
● Function template
● Alias template (since C++11)
● Variable template (since C++14)
Compiler will generate a copy for each used type
Programming in C++ 68
Template
template <typename T> // class template Output
struct Point { T x, y; };
template <typename T> // function template 3 0.3
T sum(T a, T b) { return a + b; }
3 3.14159
template <typename T> // alias template
using P = Point<T>;
template <typename T> // variable template
T pi = T(acos(-1));
int main() {
Point<int> a = {1, 2};
P<double> b = {0.1, 0.2};
cout << sum(a.x, a.y) << ' ' << sum(b.x, b.y) << '\n';
cout << pi<int> << ' ' << pi<double> << '\n';
return 0;
}
Programming in C++ 69
Template
Usually, you need to specify the the template parameters
● But sometimes you don’t need to specify them for functions and classes if
you provide template arguments
○ int x = max<int>(1, 2) works
○ int x = max(1, 2) also works
○ vector<int> v(10, 0) works
○ vector v(10, 0) also works (since C++17)
A lot of C++ Standard Library functions and classes are templates
In most cases, you don’t have to write your own templates, you just need to
know how to use templates
Programming in C++ 70
Pair
Defined in header <utility>
A struct template to store two objects
To declare a tuple storing two int types and one double type:
● tuple<int, int, double> p
● tuple p(0, 0, 0.0) (since C++17)
To access the Nth element:
● get<N>(p) (N should be a fixed number in compile time)
Programming in C++ 73
Comparison (<, <=, ==, …) works with lexicographical order if all types are
comparable
Programming in C++ 74
Tie
pair p(1, 2); Output
int x, y;
tie(x, y) = p; 1 2
cout << x << ' ' << y << '\n'; 2 2
x = 2; 1 2
cout << x << ' ' << y << '\n';
2 2
cout << [Link] << ' ' << [Link] << '\n';
p = tie(x, y);
cout << [Link] << ' ' << [Link] << '\n';
Changing the values of the tied variables won’t change the member values in
pair, so you need to tie them again and assign it to the pair
Programming in C++ 76
Sort
Defined in header <algorithm>
Sorts the elements in the range [first, last) in non-descending order, where
first and last are random access iterators
Sort
To sort a int vector in reverse order:
● sort([Link](), [Link](), greater<int>())
● sort([Link](), [Link](), greater<>()) (since C++14)
● sort([Link](), [Link](), greater{}) (since C++14)
● sort([Link](), [Link]())
● sort([Link](), [Link]()) followed by reverse([Link](),
[Link]())
Reverse
Defined in header <algorithm>
Reverses the order of the elements in the range [first, last)
Programming in C++ 81
Reverse
vector a = {1, 4, 2, 3, 5}; Output
reverse([Link](), [Link]());
for (auto x : a) cout << x << ' '; 5 3 2 4 1
cout << '\n';
Programming in C++ 82
Comparison function
The comparison function should take two parameters a and b and return a
boolean value indicating whether a < b
How to write it?
Two main ways:
● A normal function
● A lambda expression (since C++11)
Programming in C++ 83
Unique
Defined in header <algorithm>
Eliminates all except the first element from every consecutive group of
equivalent elements from the range [first, last) and returns a past-the-end
iterator for the new logical end of the range
Usually followed by calling erase() which clears the unused range at the end
Programming in C++ 91
Unique
vector a = {1, 2, 2, 4, 2}; Output
auto it = unique([Link](), [Link]());
cout << it - [Link]() << '\n'; 4
cout << [Link]() << '\n'; 5
for (auto x : a) cout << x << ' '; 1 2 4 2 2
cout << '\n';
4
[Link](it, [Link]());
1 2 4 2
cout << [Link]() << '\n';
for (auto x : a) cout << x << ' ';
cout << '\n';
Programming in C++ 92
Discretization
By using the above algorithms, we can do discretization very easily:
● Make a copy of the original array
● Sort it, then all elements of the same values will be in continuous ranges
● Call unique() to get an array containing distinct elements
● Use lower_bound() to find the rank of each element in the original array
(which is the index of the new array + 1)
Discretization
vector a = {748934, 23, 3232, 1, 328490, 2342, 123, 1, 2342, 123, Output
3232, 1};
vector b = a; 7 2 5 1 6 4 3 1 4 3 5
sort([Link](), [Link]()); 1
[Link](unique([Link](), [Link]()), [Link]());
for (auto& x : a) x = lower_bound([Link](), [Link](), x) - [Link]()
+ 1;
for (auto x : a) cout << x << ' ';
cout << '\n';
Programming in C++ 94
Application - discretization
Please read the problem S152 - Apple Garden
Programming in C++ 95
Deque
Defined in header <deque>
A double-ended queue with random access
Deque
deque q{4, 5, 6}; Output
q.emplace_front(3);
q.emplace_back(7); 5
cout << q[2] << '\n'; 6
q.pop_back(); 4
cout << [Link]() << '\n';
4 5 6
q.pop_front();
cout << [Link]() << '\n';
for (auto x : q) cout << x << ' ';
cout << '\n';
Programming in C++ 97
Deque
It seems that deque is stronger than vector, why we use vector?
The answer is the memory usage:
● deque: n + c1
● vector: 2n + c2
● c1 > c2
The internal storage of deque are not contiguous
Be careful of the memory used by many deques of small size
Programming in C++ 98
Deque
std::vector std::deque
Programming in C++ 99
Stack
Defined in header <stack>
A container adaptor for a LIFO (last-in, first-out) data structure
Default container: deque
No random access and iterators
Stack
stack<int> st; Output
[Link](1);
[Link](2); 2
cout << [Link]() << '\n'; 1
[Link]();
cout << [Link]() << '\n';
Programming in C++ 101
Queue
Defined in header <queue>
A container adaptor for a FIFO (first-in, first-out) data structure
Default container: deque
No random access and iterators
Queue
queue<int> q; Output
[Link](1);
[Link](2); 1
cout << [Link]() << '\n'; 2
[Link]();
cout << [Link]() << '\n';
Programming in C++ 103
List
Defined in header <list>
Implemented as a doubly-linked list
No random access
List
To insert x before the element pointed by it:
● [Link](it, x)
● Returns an iterator pointing to the element inserted
To remove the element pointed by it:
● [Link](it)
● Returns an iterator pointing to the next element after it
Programming in C++ 105
List
list l{10, 20};
Output
l.emplace_back(30);
l.emplace_front(0);
cout << [Link]() << ' ' << [Link]() << '\n'; 0 30
auto it = [Link](); 0 20 30
it++;
it = [Link](it); 0 20 25 30
for (auto x : l) cout << x << ' '; 0 20 25 30 40
cout << '\n';
it++; 25
it = [Link](it, 25);
for (auto x : l) cout << x << ' ';
cout << '\n';
[Link]([Link](), 40);
for (auto x : l) cout << x << ' ';
cout << '\n';
cout << *it << '\n';
Programming in C++ 106
Priority queue
Defined in header <queue>
Implementation of a max heap
Default container: vector
Priority queue
priority_queue<int> q; Output
[Link](1);
[Link](3); 3
[Link](2); 2
cout << [Link]() << '\n';
[Link]();
cout << [Link]() << '\n';
Programming in C++ 108
Min heap
If you want a min heap, there are 3 ways:
● Use greater
○ priority_queue<int, vector<int>, greater<int>> q
○ You can use alias template so you can use it in the future easily:
■ template<typename T> using min_heap = priority_queue<T,
vector<T>, greater<T>>
■ min_heap<int> q
● Define a struct that contains operator()
● Define a lambda expression, and use decltype() to get its type
Programming in C++ 109
Set
set s{1, 2, 2, 3, 4}; Output
[Link](5);
cout << [Link]() << '\n'; 5
[Link](2);
3
auto it = s.lower_bound(2);
if (it != [Link]()) cout << *it << '\n'; 5
else cout << "None\n"; 3
it = [Link](5).first;
1 3 4
cout << *it << '\n';
[Link](it);
it = [Link](3);
if (it != [Link]()) cout << *it << '\n';
else cout << "None\n";
for (auto x : s) cout << x << ' ';
cout << '\n';
Programming in C++ 114
Multiset
multiset s{1, 2, 2, 3, 4}; Output
[Link](5);
cout << [Link]() << '\n'; 6
[Link](2);
3
auto it = s.lower_bound(2);
if (it != [Link]()) cout << *it << '\n'; 5
else cout << "None\n"; 3
it = [Link](5);
1 3 4 5
cout << *it << '\n';
[Link](it);
it = [Link](3);
if (it != [Link]()) cout << *it << '\n';
else cout << "None\n";
for (auto x : s) cout << x << ' ';
cout << '\n';
Programming in C++ 115
Map
map<int, int> mp; Output
auto it = [Link](1, 2).first;
cout << it->first << ' ' << it->second << '\n'; 1 2
mp[2] = 0; 2 1
mp[2]++; 1 2
it = [Link](2);
2 1
if (it != [Link]()) cout << it->first << ' ' << it->second << '\n';
else cout << "None\n";
for (auto [key, val] : mp) cout << key << ' ' << val << '\n';
Bitset
Defined in header <bitset>
Represents a fixed-size sequence of n bits
Supports bitwise operations (&, ^, |, …)
Can use operator[] to access values (like a boolean array)
Bitset
To set a bit to 1: [Link](x) / s[x] = 1
To set a bit to 0: [Link](x) / s[x] = 0
To flip a bit: [Link](x)
To set all bits to 1: [Link]()
To set all bits to 0: [Link]()
To flip all bits: [Link]()
To count number of bits set to 1: [Link]()
Programming in C++ 121
Bitset
bitset<10> s(100); Output
cout << s << '\n';
cout << [Link]() << '\n'; 0001100100
[Link](0); 3
cout << s << '\n'; 0001100101
[Link](3);
0001100101
cout << s << '\n';
0001100111
[Link](1);
0001000111
cout << s << '\n';
s[5] = 0;
0000000000
cout << s << '\n';
[Link]();
cout << s << '\n';
Programming in C++ 122
Application - bitset
Please read the problem M2002 - Corona and Movies
Programming in C++ 123
Non-standard Library
Possibly not existing in some C++ compilers
Usable in g++ (which is used in HKOI Online Judge)
Lack of good (and official) documentation
[Link]
[Link]
ta-structures/OrderStatisticTree.h
[Link]
[Link]
[Link]
Programming in C++ 129
Conclusion
● C++ standard libraries are useful
● You can save a lot of time during the contest by using them appropriately
● Every problem can be your practice problem
● Try to develop your own coding style base on them
● cppreference is always your good friend
Programming in C++ 130
Reference
[Link]
Standard Template Library - Wikipedia
C++ Standard Library - Wikipedia
[Link]
[Link]
[Link]
[Link]