{}DSA Atlas

Python & C++ Quick Reference

The standard-library tools you'll reach for constantly in Python and C++ — containers, sorting, heaps, bisect, strings and common gotchas.

Containers at a glance

NeedPythonC++
dynamic arraylistvector<T>
stacklist (append/pop)vector<T> or stack<T>
queue / dequecollections.dequequeue<T> / deque<T>
hash map / setdict / setunordered_map / unordered_set
countercollections.Counterunordered_map<T, int>
default dictcollections.defaultdictmap[key] auto-initializes
ordered map / setsortedcontainers.SortedList/SortedDictmap / set / multiset
min-heapheapq on a listpriority_queue<T, vector<T>, greater<T>>
max-heapheapq with negated valuespriority_queue<T>
fixed-size bitsetint as bitsbitset<N>

Python essentials

Python
from collections import deque, Counter, defaultdict, OrderedDict
from heapq import heappush, heappop, heapify, nlargest, nsmallest
from bisect import bisect_left, bisect_right, insort
from functools import cache, lru_cache, cmp_to_key, reduce
from itertools import accumulate, combinations, permutations, product, pairwise, groupby
from math import gcd, lcm, inf, comb, perm, isqrt
import sys
sys.setrecursionlimit(10**6)

# lists
a = [0] * n
grid = [[0] * C for _ in range(R)]      # NOT [[0] * C] * R
a.sort(key=lambda x: (-x[1], x[0]))     # stable, custom key
b = sorted(a, reverse=True)
a[::-1]; a[i:j]                          # slices copy: O(k)
idx = max(range(n), key=a.__getitem__)   # argmax

# dict / set
d.get(k, default); d.setdefault(k, []).append(v)
for k, v in d.items(): ...
s = set(); s.add(x); s.discard(x); x in s

# counters
c = Counter(s); c.most_common(k); c[x] += 1
c1 == c2                                  # multiset equality

# strings
"".join(parts); s.split(); s.strip(); s.isdigit(); s.isalpha(); s.lower()
ord("a"); chr(97); s[::-1]; s.find(t); s.count(t)
f"{x:.2f}"

# deque
q = deque([start]); q.append(x); q.appendleft(x); q.pop(); q.popleft()

# heap
h = []; heappush(h, (priority, item)); p, item = heappop(h); h[0]

# bisect on sorted list
i = bisect_left(a, x)                    # first >= x
j = bisect_right(a, x)                   # first > x

# memoized recursion
@cache
def f(i, j): ...
f.cache_clear()

# infinity and big ints
best = inf; neg = -inf                   # Python ints never overflow

Python gotchas

  • Default mutable arguments (def f(x=[])) are shared between calls.
  • [[0] * C] * R creates R references to one row.
  • -7 // 2 == -4 (floor division); use int(a / b) to truncate toward zero.
  • -7 % 3 == 2 (always non-negative for positive modulus).
  • Recursion limit 1000 by default; deep recursion may still crash — prefer iteration.
  • String concatenation in loops is O(n²); build a list and join.
  • list.pop(0) and list.insert(0, x) are O(n).

C++ essentials

C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

// vectors
vector<int> a(n, 0);
vector<vector<int>> grid(R, vector<int>(C, 0));
sort(a.begin(), a.end());
sort(a.begin(), a.end(), greater<int>());
sort(a.begin(), a.end(), [](const auto& x, const auto& y) { return x[1] < y[1]; });
reverse(a.begin(), a.end());
int mx = *max_element(a.begin(), a.end());
ll sum = accumulate(a.begin(), a.end(), 0LL);   // 0LL, not 0, to avoid overflow
a.erase(unique(a.begin(), a.end()), a.end());   // dedupe a sorted vector

// binary search on sorted vector
auto it = lower_bound(a.begin(), a.end(), x);   // first >= x
int idx = it - a.begin();
bool found = binary_search(a.begin(), a.end(), x);

// hash map / set
unordered_map<string, int> cnt; cnt[s]++;
if (cnt.count(k)) {}                    // check without inserting
unordered_set<int> seen; seen.insert(x); seen.erase(x);

// ordered set / map
set<int> st; st.insert(x);
auto lb = st.lower_bound(x);            // member function: O(log n)
if (lb != st.begin()) { int pred = *prev(lb); }
map<int, int> m; m.begin()->first; m.rbegin()->first;   // min / max key
multiset<int> ms; ms.erase(ms.find(x)); // erase ONE copy

// heaps
priority_queue<int> maxh;
priority_queue<int, vector<int>, greater<int>> minh;
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;

// strings
string s = "abc"; s += 'd'; s.substr(pos, len); s.find("bc");
to_string(42); stoi("42"); stoll("123456789012");
reverse(s.begin(), s.end());

// pairs / tuples and structured bindings
pair<int,int> p = {1, 2}; auto [x, y] = p;
tuple<int,int,int> t = {1, 2, 3}; auto [u, v, w] = t;

// lambdas and recursive lambdas
function<int(int)> dfs = [&](int u) -> int { return u; };

// bits
__builtin_popcount(x); __builtin_popcountll(x); __builtin_ctz(x); 1LL << k;

// limits
INT_MAX; LLONG_MAX; const ll INF = 1e18;

// fast I/O (competitive programming)
ios::sync_with_stdio(false); cin.tie(nullptr);

C++ gotchas

  • int overflows at ~2.1 × 10⁹: use long long for sums, products, and distances.
  • accumulate(..., 0) accumulates in int even for long long vectors — pass 0LL.
  • map[key] inserts a default value when reading a missing key.
  • a.size() is unsigned: a.size() - 1 underflows when empty. Cast: (int)a.size() - 1.
  • priority_queue is a max-heap; comparator semantics are "lower priority".
  • lower_bound(set.begin(), set.end(), x) is O(n); use set.lower_bound(x).
  • Comparators must be strict (<, never <=).
  • Recursive lambdas need function<> (or a this auto& self parameter in C++23).
  • -7 / 2 == -3 and -7 % 2 == -1 (truncation toward zero).

Equivalents side by side

TaskPythonC++
sort descendinga.sort(reverse=True)sort(a.rbegin(), a.rend())
sumsum(a)accumulate(a.begin(), a.end(), 0LL)
min/maxmin(a), max(a)*min_element(...), *max_element(...)
count valuea.count(x)count(a.begin(), a.end(), x)
reversea.reverse()reverse(a.begin(), a.end())
next permutationitertools.permutationsnext_permutation(a.begin(), a.end())
gcdmath.gcdstd::gcd
integer sqrtmath.isqrt(n)(ll)sqrtl(n) then adjust
infinityfloat('inf') / math.infINT_MAX, LLONG_MAX, 1e18
modular powerpow(a, e, m)write power() (see Math)