The language-level facts that decide WA/TLE/RE before any algorithm does. Everything here is GCC on a 64-bit Linux judge (Codeforces, AtCoder, ICPC), C++20 unless noted.
The template
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using i128 = __int128;
#define all(x) (x).begin(), (x).end()
#define sz(x) int((x).size())
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
void solve() {
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int t = 1;
cin >> t;
while (t--) solve();
}ckmin(d[v], d[u] + w)both relaxes and reports whether it changed, which is exactly what Dijkstra, Bellman-Ford and DP relaxations want.- Seed randomness with time. Fixed seeds make hashing and random pivots hackable.
- Remove
cin.tie(nullptr)only if you rely on auto-flush; for interactive problems flush explicitly instead (see Interactive Problems). - The full library lives in Templates; this page is about the language.
Integer types and overflow
| Type | Max | Use |
|---|---|---|
int | indices, counts | |
unsigned | hashing mod | |
long long | sums, products of two ints | |
unsigned long long | hashing mod , bitsets of 64 | |
__int128 | for , exact geometry with coordinates cubed |
The overflow rule
The type of
a * bis decided by the operands, not by the variable you assign to.ll x = a * b;withint a, boverflows. Write1LL * a * b.
Overflow checklist:
- Sum of values of size needs
ll.accumulate(all(v), 0)sums inint; write0LL. 1 << 40is UB; write1LL << 40. Shifting by width is UB even for unsigned.INF = 1e18plus anything overflows. UseINF = 4e18only if you never add to it, otherwiseLLONG_MAX / 4, and guardif (d[u] == INF) continue;.abs(INT_MIN)and-LLONG_MINoverflow.- Signed overflow is UB, and the optimizer exploits it (loops whose bound check silently disappears). Unsigned wraps mod and is well defined.
- Overflow-checked multiply:
__builtin_mul_overflow(a, b, &res)returns true on overflow. Also__builtin_add_overflow.
__int128 has no stream I/O:
string to_str(i128 x) {
if (x == 0) return "0";
bool neg = x < 0; if (neg) x = -x;
string s;
while (x) s += char('0' + x % 10), x /= 10;
if (neg) s += '-';
return {s.rbegin(), s.rend()};
}Division, modulo and rounding
C++ truncates toward zero: -7 / 2 == -3, -7 % 2 == -1. Mathematical versions:
ll floordiv(ll a, ll b) { return a / b - ((a % b != 0) && ((a < 0) != (b < 0))); }
ll ceildiv(ll a, ll b) { return a / b + ((a % b != 0) && ((a < 0) == (b < 0))); }
ll md(ll a, ll m) { a %= m; return a < 0 ? a + m : a; }(a + b - 1) / bis ceil only for .- Integer square root:
ll r = sqrtl(n); while (r * r > n) r--; while ((r + 1) * (r + 1) <= n) r++;. Never trustsqrtalone near . - Integer log:
__lg(x)is for ; C++20bit_width(x) - 1is the same. powreturnsdouble. Never use it for integers.
size() is unsigned
v.size() - 1 on an empty vector is , so for (int i = 0; i < v.size() - 1; i++) runs forever. Cast with sz(v). Same trap with s.size() - k in string loops.
Containers
| Container | Access | Insert / erase | Notes |
|---|---|---|---|
vector | amortized at back | contiguous, by far the fastest | |
deque | at both ends | chunked, around 2x slower than vector, high memory per instance | |
set, map, multiset | — | red-black tree, ordered, predecessor/successor | |
unordered_map | avg | avg | hackable, large constant, use a custom hash |
priority_queue | top | max-heap by default | |
bitset<N> | — | word-parallel ops in | |
PBDS tree | — | adds order_of_key, find_by_order (PBDS) |
The six classic traps:
std::lower_bound(all(s), x)on asetis (no random access). Uses.lower_bound(x).ms.erase(x)on a multiset erases every copy. Usems.erase(ms.find(x)).uniqueonly moves adjacent duplicates to the back. Sort first, thenv.erase(unique(all(v)), v.end()).- Iterator invalidation:
vectoron reallocation (includingpush_backwhile iterating),dequeon any insertion,set/maponly for the erased node.auto& x = v[0]; v.push_back(..)leavesxdangling. map[k]insertskif absent. Usecount/find/contains(C++20) in read-only checks, or the map grows.vector<bool>is bit-packed with proxy references. Usevector<char>for a real boolean array,bitsetfor bit tricks.
Min-heap: priority_queue<T, vector<T>, greater<T>>. There is no decrease-key; push the new value and skip stale entries on pop (lazy deletion).
Hashing safely
The default hash<long long> is the identity, so anti-hash tests force per operation. Use splitmix64 with a runtime seed:
struct SafeHash {
static ull splitmix64(ull x) {
x += 0x9e3779b97f4a7c15ULL;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
return x ^ (x >> 31);
}
size_t operator()(ull x) const {
static const ull SEED = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + SEED);
}
};
unordered_map<ll, int, SafeHash> mp;
mp.reserve(1 << 20); mp.max_load_factor(0.25); // often 2x fasterFor pairs, hash x * 1'000'000'007 + y or combine two splitmix values. __gnu_pbds::gp_hash_table<ll, int, SafeHash> is usually 2-3x faster than unordered_map. Often the fastest of all is to avoid hashing: sort plus binary search, or coordinate compression into an array.
Algorithms worth knowing by heart
sort(all(a)); stable_sort(all(a)); // introsort; stable = merge sort
nth_element(a.begin(), a.begin() + k, a.end()); // k-th smallest in O(n) average
partial_sort(a.begin(), a.begin() + k, a.end()); // smallest k sorted, O(n log k)
lower_bound / upper_bound / equal_range // first >= x, first > x, both
a.erase(unique(all(a)), a.end()); // dedupe a sorted range
next_permutation(all(a)); // start from sorted to get all n!
iota(all(p), 0); // 0, 1, 2, ...
partial_sum(all(a), pre.begin() + 1); // prefix sums
rotate(a.begin(), a.begin() + k, a.end()); // left rotate by k
merge(all(a), all(b), back_inserter(c)); // merge two sorted ranges
inplace_merge(first, mid, last); // merge sort step
max_element / min_element / minmax_element // return iterators
count_if / all_of / any_of / none_of / find_if
gcd(a, b); lcm(a, b); // <numeric>, C++17
midpoint(a, b); // no overflow, C++20C++20 <bit>: popcount, countl_zero, countr_zero, bit_width, bit_floor, bit_ceil, has_single_bit (unsigned arguments only). See Bit Tricks.
C++20 ranges shorten common code: ranges::sort(a), ranges::lower_bound(a, x), ranges::max(a), for (int i : views::iota(0, n)), for (auto x : a | views::reverse).
Comparators
A comparator must be a strict weak ordering: cmp(a, a) is false, and incomparability is transitive. A comparator with <= is undefined behaviour and does crash std::sort (it walks off the array) on large inputs.
sort(all(v), [](const auto& a, const auto& b) {
if (a.first != b.first) return a.first < b.first;
return a.second > b.second; // tie-break descending
});
sort(all(v), [](auto& a, auto& b) { return tie(a.x, b.y) < tie(b.x, a.y); }); // lexicographic via tuples- For an exchange-argument sort (
abeforebiff ), verify transitivity. Sorting fractions must comparea1 * b2 < a2 * b1inll/i128, never asdouble. - Floating comparators with an epsilon are not strict weak orderings. Never put them in a
set. - For a custom
setorder with equal keys, the set treats!cmp(a,b) && !cmp(b,a)as equal and drops duplicates. Add an id as a tie-breaker.
References, copies, lambdas
for (auto& [k, v] : mp) v *= 2; // modifies
for (const auto& s : strs) use(s); // no copy
for (auto s : strs) use(s); // copies every string: silent TLEPass containers by reference. A recursive function taking vector<int> g by value copies it on every call.
Recursive lambdas:
auto dfs = [&](auto&& self, int v, int p) -> void {
for (int u : g[v]) if (u != p) self(self, u, v);
};
dfs(dfs, 0, -1);
// C++23: auto dfs = [&](this auto&& self, int v, int p) -> void { ... }; dfs(0, -1);function<void(int,int)> also works, but it is slower (type-erased call) and cannot be inlined.
Recursion depth
Each frame costs roughly 50-200 bytes. A DFS on a path of vertices needs 100+ MB of stack.
- Codeforces and most judges give a large stack, but Windows judges default to 1 MB (Codeforces sets 256 MB).
- Options: iterative DFS with an explicit stack, BFS order processed in reverse (works for most tree DPs), or run the solution on a thread with a big stack.
- Locally:
ulimit -s unlimited, or with MinGW-Wl,--stack,268435456.
// tree DP without recursion: BFS order, then process in reverse
vector<int> order = {0}, par(n, -1);
for (int i = 0; i < sz(order); i++) {
int v = order[i];
for (int u : g[v]) if (u != par[v]) par[u] = v, order.push_back(u);
}
for (int i = n - 1; i > 0; i--) { int v = order[i]; /* combine v into par[v] */ }Recursion shapes worth recognising, beyond depth: linear (, e.g. factorial), binary split (, e.g. merge sort, segment trees), choice/enumeration (include-or-skip each element, e.g. subset backtracking), tree traversal (recurse on children), mutual recursion ( calls calls , e.g. expression parsing). Every recursive solution needs a base case, a reduction to strictly smaller instances, and a combine step; a missing or unreachable base case is a silent infinite recursion (RE, not WA), and exponential blow-up from repeated subproblems is the signal to memoize (Memoization).
Undefined behaviour that “works locally”
| Code | Problem |
|---|---|
a[i++] = i | unsequenced modification |
| reading an uninitialized local | random value; globals are zeroed, locals are not |
v[v.size()], s[-1] | out of bounds; sometimes silent |
missing return in non-void function | UB, frequently a crash with -O2 |
comparator with <= | sort reads out of range |
int overflow inside a loop condition | loop may never terminate |
| large local arrays | stack overflow. Make big arrays global or static |
| unparenthesized macros | #define SQ(a) a*a expands SQ(3+3) to 3+3*3+3=15, not 36 — always write #define SQ(a) ((a)*(a)) |
Compile locally with -D_GLIBCXX_DEBUG -fsanitize=address,undefined -g to turn most of these into immediate errors (Debugging).
Floating point
- Never compare with
==. Prefer exact integer arithmetic: compare as , distances squared, cross products inll. long doubleis 80-bit on x86 GCC (about 18-19 significant digits) and is usually worth it in geometry. Print withcout << fixed << setprecision(10).acosl(-1.0L)gives at full precision.- Details: Floating Point.
Precompute once, query many
With test cases and a global bound, build tables outside the test loop: factorials and inverse factorials, smallest prime factor, powers of the hash base, , popcount tables. Recomputing per test is a classic TLE with .
Do not memset or assign an array of size per test case when the test is tiny: the sum of is bounded, the sum of MAXN is not. Clear only what you used.
Hard-coding: if the input is a single small parameter and the answer is slow to compute, precompute answers locally (every -th value, or all of them if few), paste them into the source (judges allow about 64 KB of code) and finish from the nearest checkpoint.
Constants
const int MOD = 998244353; // = 119 * 2^23 + 1, NTT-friendly; 1e9 + 7 otherwise
const ll INF = LLONG_MAX / 4; // room to add a few without overflow
const int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
const long double PI = acosl(-1.0L);int INF = 1e9 lets INF + INF fit in ll but not in int. Pick the sentinel so the arithmetic you do on it cannot overflow, and still guard unreachable states.
A byte count in MiB divides by ; a decimal MB divides by — judges state memory limits in MiB-sized powers of two but sometimes label them “MB,” so check which is meant before trusting a tight estimate.
Utilities
Calendar (proleptic Gregorian, day 1 = 0001-01-01, 0 = Monday):
bool isLeap(ll y) { return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); }
int daysIn(ll y, int m) { static int d[] = {31,28,31,30,31,30,31,31,30,31,30,31}; return m == 2 && isLeap(y) ? 29 : d[m - 1]; }
ll daysBefore(ll y) { y--; return y * 365 + y / 4 - y / 100 + y / 400; }
ll ordinal(ll y, int m, int d) { ll r = daysBefore(y) + d; for (int i = 1; i < m; i++) r += daysIn(y, i); return r; }
int dayOfWeek(ll y, int m, int d) { return (ordinal(y, m, d) - 1) % 7; }The Gregorian calendar repeats every 400 years (146097 days, a multiple of 7), which is how “count Fridays the 13th in ” is done.
Proof: the 400-year cycle has 146097 days, a multiple of 7
In any 400 consecutive years, the leap-year rule (divisible by 4, except centuries, except multiples of 400) gives leap years, so the cycle has days. Dividing: exactly, so the day-of-week pattern (and hence the full calendar, since the leap-year rule itself has period exactly 400 years) repeats identically every 400 years — a date years later falls on the same day of the week. Tested:
ordinal/dayOfWeekabove were checked against Python’sdatetime.date.toordinal()/.weekday()for every day of years 1 and 4, and spot-checked every 7th day of years 100, 400, 401, 1600, 1700, 1752, 1900, 2000, 2024, 2400 (centuries and the 400-multiple boundaries where the rule actually branches) — all matched.
Random helpers:
ll rnd(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); }
shuffle(all(v), rng);Never use rand(): on Windows judges RAND_MAX is 32767.