In competitive programming, std::set and std::map are standard C++ associative containers that efficiently support operations like insertion, deletion, and search in time. They are usually implemented as balanced binary search trees, so all elements (keys) are kept in sorted order. This makes them very useful when you need to maintain a dynamically changing ordered set of values or key–value pairs.
std::setA set is a container that stores unique keys in sorted order. Basic properties:
insert, erase, find, lower_bound, upper_bound.Typical declaration:
std::mapA map is an ordered dictionary: it stores key–value pairs (key, value), with unique keys and keys sorted by strict weak ordering.
Basic properties:
operator[] or at.Example of a map from strings to integers:
Note: freq[key] creates the key with default value if it does not exist yet.
Problem: Given integers, find how many distinct values there are.
Idea: Insert each element into a set<int>. Since a set keeps only unique elements, the answer is just s.size().
Solution:
Problem: You are given distinct integers and queries. Each query gives a value , and you must output the smallest element in the set that is greater than or equal to , or report that it does not exist.
Idea: Store all elements in a set<int>. For each query , use lower\_bound(x) to find the first element not less than .
Solution:
Problem: Given words, output each distinct word and how many times it appears, in lexicographical order.
Idea: Use map<string,int> and increment m[word] for each input word. The map maintains sorted order of keys automatically.
Solution:
Coordinate compression is a common technique in competitive programming. We map large or arbitrary values into a smaller range while preserving order.
Problem: Given integers , replace each with its rank in the sorted list of distinct values (starting from ). Idea:
set<int> to get distinct sorted values.map<int,int> from value to compressed index.Solution:
#include <bits/stdc++.h>
using namespace std;
int main() {
set<int> s; // empty set of ints
s.insert(5);
s.insert(1);
s.insert(3);
s.insert(3); // duplicate, ignored
// s now contains {1, 3, 5}
if (s.find(3) != s.end()) {
cout << "3 is in the set\n";
}
s.erase(1); // remove key 1 if present
for (int x : s) {
cout << x << " "; // prints: 3 5
}
cout << "\n";
}
#include <bits/stdc++.h>
using namespace std;
int main() {
map<string, int> freq;
freq["apple"]++;
freq["banana"] += 2;
freq["orange"] = 5;
// Iteration goes in lexicographical order of keys
for (auto &[word, count] : freq) {
cout << word << " -> " << count << "\n";
}
if (freq.count("apple")) {
cout << "apple appears " << freq["apple"] << " times\n";
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
set<int> s;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
s.insert(x);
}
cout << s.size() << "\n";
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
set<int> s;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
s.insert(x);
}
while (q--) {
int x;
cin >> x;
auto it = s.lower_bound(x);
if (it == s.end()) {
cout << "NO\n";
} else {
cout << *it << "\n";
}
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
map<string, int> freq;
for (int i = 0; i < n; i++) {
string w;
cin >> w;
freq[w]++; // creates key if not present
}
for (auto &[word, count] : freq) {
cout << word << " " << count << "\n";
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
set<int> s(a.begin(), a.end()); // distinct sorted values
map<int, int> comp; // value -> compressed index
int id = 0;
for (int x : s) {
comp[x] = id++;
}
for (int i = 0; i < n; i++) {
a[i] = comp[a[i]];
}
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
cout << "\n";
return 0;
}