Professional Documents
Culture Documents
Omogen Heap
Simon Lindholm, Johan Sannemo, Mårten Wiman
2021-01-10
1 Contest 1 troubleshoot.txt 52 lines
ed − bf
Pre-submit:
ax + by = e x=
2 Mathematics 1 Write a few simple test cases if sample is not enough. ad − bc
⇒
Are time limits close? If so, generate max cases. cx + dy = f af − ec
Is the memory usage fine? y=
3 Data structures 3 Could anything overflow? ad − bc
Make sure to submit the right file.
In general, given an equation Ax = b, the solution to a variable
4 Numerical 5 Wrong answer: xi is given by
Print your solution! Print debug output, as well.
Are you clearing all data structures between test cases?
det A0i
5 Number theory 8 xi =
Can your algorithm handle the whole range of input? det A
Read the full problem statement again. 0
6 Combinatorial 10 Do you handle all corner cases correctly? where Ai is A with the i’th column replaced by b.
Have you understood the problem correctly?
7 Graph 11
Any uninitialized variables?
Any overflows?
2.2 Recurrences
Confusing N and M, i and j, etc.?
Are you sure your algorithm works?
If an = c1 an−1 + · · · + ck an−k , and r1 , . . . , rk are distinct roots of
8 Geometry 17 What special cases have you not thought of? xk + c1 xk−1 + · · · + ck , there are d1 , . . . , dk s.t.
Are you sure the STL functions you use work as you think?
9 Strings 21 Add some assertions, maybe resubmit. an = d1 r1n + · · · + dk rkn .
Create some testcases to run your algorithm on.
Go through the algorithm for a simple case.
10 Various 22 Go through this list again. Non-distinct roots r become polynomial factors, e.g.
Explain your algorithm to a teammate. an = (d1 n + d2 )rn .
Ask the teammate to look at your code.
Contest (1) Go for a small walk, e.g. to the toilet.
Is your output format correct? (including whitespace) 2.3 Trigonometry
Rewrite your solution from the start or let a teammate do it.
template.cpp 14 lines sin(v + w) = sin v cos w + cos v sin w
Runtime error:
#include <bits/stdc++.h> Have you tested all corner cases locally?
using namespace std; Any uninitialized variables?
cos(v + w) = cos v cos w − sin v sin w
Are you reading or writing outside the range of any vector?
#define rep(i, a, b) for(int i = a; i < (b); ++i) Any assertions that might fail?
#define all(x) begin(x), end(x) Any possible division by 0? (mod 0 for example)
#define sz(x) (int)(x).size() Any possible infinite recursion?
typedef long long ll; tan v + tan w
Invalidated pointers or iterators? tan(v + w) =
typedef pair<int, int> pii; Are you using too much memory? 1 − tan v tan w
typedef vector<int> vi; Debug with resubmits (e.g. remapped signals, see Various). v+w v−w
sin v + sin w = 2 sin cos
int main() { Time limit exceeded: 2 2
cin.tie(0)->sync_with_stdio(0); Do you have any possible infinite loops? v+w v−w
cin.exceptions(cin.failbit); What is the complexity of your algorithm? cos v + cos w = 2 cos cos
}
2 2
Are you copying a lot of unnecessary data? (References)
How big is the input and output? (consider scanf) (V + W ) tan(v − w)/2 = (V − W ) tan(v + w)/2
Avoid vector, map. (use arrays/unordered_map)
.bashrc 3 lines What do your teammates think about your algorithm? where V, W are lengths of sides opposite angles v, w.
alias c=’g++ -Wall -Wconversion -Wfatal-errors -g -std=c++14 \
Memory limit exceeded:
-fsanitize=undefined,address’
What is the max amount of memory your algorithm should need?
a cos x + b sin x = r cos(x − φ)
xmodmap -e ’clear lock’ -e ’keycode 66=less greater’ #caps = <>
Are you clearing all data structures between test cases? a sin x + b cos x = r sin(x + φ)
.vimrc √
6 lines where r = a2 + b2 , φ = atan2(b, a).
set cin aw ai is ts=4 sw=4 tm=50 nu noeb bg=dark ru cul Mathematics (2)
sy on | im jk <esc> | im kj <esc> | no ; :
" Select region and then type :Hash to hash your selection. 2.4 Geometry
" Useful for verifying that there aren’t mistypes. 2.1 Equations
ca Hash w !cpp -dD -P -fpreprocessed \| tr -d ’[:space:]’ \ 2.4.1 Triangles
\| md5sum \| cut -c-6
√ Side lengths: a, b, c
2 −b ± b2 − 4ac a+b+c
hash.sh ax + bx + c = 0 ⇒ x = Semiperimeter: p =
3 lines 2a 2
p
# Hashes a file, ignoring all whitespace and comments. Use for Area: A = p(p − a)(p − b)(p − c)
# verifying that code was correctly typed.
cpp -dD -P -fpreprocessed | tr -d ’[:space:]’| md5sum |cut -c-6 abc
The extremum is given by x = −b/2a. Circumradius: R =
4A
KTH template .bashrc .vimrc hash troubleshoot 2
A Integration by parts: 2.8.1 Discrete distributions
Inradius: r =
p
Binomial distribution
Z b b
Length √of median (divides triangle into two equal-area triangles):
Z
ma = 21 2b2 + 2c2 − a2 f (x)g(x)dx = [F (x)g(x)]ba − F (x)g 0 (x)dx
a a
Length The number of successes in n independent yes/no experiments,
v of "bisector (divides angles in two):
u 2 # each which yields success with probability p is
2.6 Sums
u a Bin(n, p), n = 1, 2, . . . , 0 ≤ p ≤ 1.
sa = tbc 1 −
b+c
cb+1 − ca
!
sin α sin β sin γ 1 ca + ca+1 + · · · + cb = , c 6= 1 p(k) =
n k
p (1 − p)n−k
Law of sines: = = = c−1 k
a b c 2R
Law of cosines: a2 = b2 + c2 − 2bc cos α
α+β n(n + 1) µ = np, σ 2 = np(1 − p)
tan 1 + 2 + 3 + ··· + n =
a+b 2 2 Bin(n, p) is approximately Po(np) for small p.
Law of tangents: = n(2n + 1)(n + 1)
a−b α−β 2 2 2 2
tan 1 + 2 + 3 + ··· + n =
2 6 First success distribution
3 3 3 3 n2 (n + 1)2
2.4.2 Quadrilaterals 1 + 2 + 3 + ··· + n =
4 The number of trials needed to get the first success in
With side lengths a, b, c, d, diagonals e, f , diagonals angle θ, area 4 4 4 4 n(n + 1)(2n + 1)(3n2 + 3n − 1) independent yes/no experiments, each wich yields success with
1 + 2 + 3 + ··· + n = probability p is Fs(p), 0 ≤ p ≤ 1.
A and magic flux F = b2 + d2 − a2 − c2 : 30
p(k) = p(1 − p)k−1 , k = 1, 2, . . .
p
4A = 2ef · sin θ = F tan θ = 4e2 f 2 − F 2 1 2 1−p
µ= ,σ =
2.7 Series p p2
◦
For cyclic quadrilateralspthe sum of opposite angles is 180 , x2 x3 Poisson distribution
ex = 1 + x + + + . . . , (−∞ < x < ∞)
ef = ac + bd, and A = (p − a)(p − b)(p − c)(p − d). 2! 3!
The number of events occurring in a fixed period of time t if these
2.4.3 Spherical coordinates x2 x3 x4 events occur with a known average rate κ and independently of
ln(1 + x) = x − + − + . . . , (−1 < x ≤ 1)
2 3 4 the time since the last event is Po(λ), λ = tκ.
z √ x x2 2x3 5x4 λk
1+x=1+ − + − + . . . , (−1 ≤ x ≤ 1) p(k) = e−λ
r 2 8 32 128 k!
, k = 0, 1, 2, . . .
y x3 x5 x7
sin x = x − + − + . . . , (−∞ < x < ∞) µ = λ, σ 2 = λ
3! 5! 7!
x x2 x4 x6 2.8.2 Continuous distributions
cos x = 1 − + − + . . . , (−∞ < x < ∞)
2! 4! 6! Uniform distribution
p
x = r sin θ cos φ r = xp 2 + y2 + z2
y = r sin θ sin φ θ = acos(z/ x2 + y 2 + z 2 ) 2.8 Probability theory If the probability density function is constant between a and b
z = r cos θ φ = atan2(y, x) and 0 elsewhere it is U(a, b), a < b.
Let X be a discrete random variable with probability pX (x) of
1
assuming theP value x. It will then have an expected value (mean) b−a
a<x<b
f (x) =
2.5 Derivatives/Integrals µ = E(X) = x xpX (x) and variance 0 otherwise
σ 2 = V (X) = E(X 2 ) − (E(X))2 = x (x − E(X))2 pX (x) where σ
P
is the standard deviation. If X is instead continuous it will have a+b 2 (b − a)2
µ= ,σ =
d 1 d 1 a probability density function fX (x) and the sums above will 2 12
arcsin x = √ arccos x = − √
dx 1 − x2 dx 1 − x2 instead be integrals with pX (x) replaced by fX (x). Exponential distribution
d d 1 Expectation is linear:
tan x = 1 + tan2 x arctan x = The time between events in a Poisson process is
dx dx 1 + x2
Z
ln | cos ax|
Z
sin ax − ax cos ax E(aX + bY ) = aE(X) + bE(Y ) Exp(λ), λ > 0.
tan ax = − λe−λx x ≥ 0
x sin ax =
a a2 f (x) =
Z √ Z ax For independent X and Y , 0 x<0
2 π e
e−x = erf(x) xeax dx = 2 (ax − 1) 1 2 1
2 a V (aX + bY ) = a2 V (X) + b2 V (Y ). µ= ,σ = 2
λ λ
KTH OrderStatisticTree HashMap SegmentTree LazySegmentTree UnionFindRollback 3
Normal distribution using Tree = tree<T, null_type, less<T>, rb_tree_tag, }
tree_order_statistics_node_update>; else val = v[lo];
}
Most real random values with mean µ and variance σ 2 are well void example() { int query(int L, int R) {
described by N (µ, σ 2 ), σ > 0. Tree<int> t, t2; t.insert(8); if (R <= lo || hi <= L) return -inf;
auto it = t.insert(10).first; if (L <= lo && hi <= R) return val;
1 (x−µ)2 assert(it == t.lower_bound(9)); push();
−
f (x) = √ e 2σ2 assert(t.order_of_key(10) == 1); return max(l->query(L, R), r->query(L, R));
2πσ 2 assert(t.order_of_key(11) == 2); }
assert(*t.find_by_order(0) == 8); void set(int L, int R, int x) {
If X1 ∼ N (µ1 , σ12 ) and X2 ∼ N (µ2 , σ22 ) then t.join(t2); // assuming T < T2 or T > T2, merge t2 into t if (R <= lo || hi <= L) return;
} if (L <= lo && hi <= R) mset = val = x, madd = 0;
else {
aX1 + bX2 + c ∼ N (µ1 + µ2 + c, a2 σ12 + b2 σ22 ) push(), l->set(L, R, x), r->set(L, R, x);
HashMap.h
Description: Hash map with mostly the same API as unordered map, but val = max(l->val, r->val);
∼3x faster. Uses 1.5x memory. Initial capacity must be a power of 2 (if }
2.9 Markov chains provided). d77092, 7 lines
}
void add(int L, int R, int x) {
#include <bits/extc++.h> if (R <= lo || hi <= L) return;
A Markov chain is a discrete random process with the property // To use most b i t s rather than j u s t the lowest ones : if (L <= lo && hi <= R) {
that the next state depends only on the current state. Let struct chash { // large odd number for C if (mset != inf) mset += x;
X1 , X2 , . . . be a sequence of random variables generated by the const uint64_t C = ll(4e18 * acos(0)) | 71; else madd += x;
ll operator()(ll x) const { return __builtin_bswap64(x*C); } val += x;
Markov process. Then there is a transition matrix P = (pij ), }; }
with pij = Pr(Xn = i|Xn−1 = j), and p(n) = Pn p(0) is the __gnu_pbds::gp_hash_table<ll,int,chash> h({},{},{},{},{1<<16}); else {
(n) push(), l->add(L, R, x), r->add(L, R, x);
probability distribution for Xn (i.e., pi = Pr(Xn = i)), where val = max(l->val, r->val);
(0)
p is the initial distribution. SegmentTree.h
Description: Zero-indexed max-tree. Bounds are inclusive to the left and }
exclusive to the right. Can be changed by modifying T, f and unit. }
π is a stationary distribution if π = πP. If the Markov chain is Time: O (log N ) void push() {
0f4bdb, 19 lines if (!l) {
irreducible (it is possible to get to any state from any state), then
struct Tree { int mid = lo + (hi - lo)/2;
πi = E(T1 i ) where E(Ti ) is the expected time between two visits in typedef int T; l = new Node(lo, mid); r = new Node(mid, hi);
state i. πj /πi is the expected number of visits in state j between static constexpr T unit = INT_MIN; }
T f(T a, T b) { return max(a, b); } // (any associative fn ) if (mset != inf)
two visits in state i. vector<T> s; int n; l->set(lo,hi,mset), r->set(lo,hi,mset), mset = inf;
Tree(int n = 0, T def = unit) : s(2*n, def), n(n) {} else if (madd)
For a connected, undirected and non-bipartite graph, where the void update(int pos, T val) { l->add(lo,hi,madd), r->add(lo,hi,madd), madd = 0;
transition probability is uniform among all neighbors, πi is for (s[pos += n] = val; pos /= 2;) }
s[pos] = f(s[pos * 2], s[pos * 2 + 1]); };
proportional to node i’s degree. }
T query(int b, int e) { // query [ b , e)
A Markov chain is ergodic if the asymptotic distribution is T ra = unit, rb = unit;
independent of the initial distribution. A finite Markov chain is for (b += n, e += n; b < e; b /= 2, e /= 2) {
UnionFindRollback.h
Description: Disjoint-set data structure with undo. If undo is not needed,
ergodic iff it is irreducible and aperiodic (i.e., the gcd of cycle if (b % 2) ra = f(ra, s[b++]); skip st, time() and rollback().
if (e % 2) rb = f(s[--e], rb);
lengths is 1). limk→∞ Pk = 1π. }
Usage: int t = uf.time(); ...; uf.rollback(t);
Time: O (log(N )) de4ad0, 21 lines
return f(ra, rb);
A Markov chain is an A-chain if the states can be partitioned } struct RollbackUF {
into two sets A and G, such that all states in A are absorbing }; vi e; vector<pii> st;
(pii = 1), and all states in G leads to an absorbing state in A. RollbackUF(int n) : e(n, -1) {}
The probability for absorption in state i ∈ A, when the initial LazySegmentTree.h int size(int x) { return -e[find(x)]; }
P Description: Segment tree with ability to add or set values of large intervals, int find(int x) { return e[x] < 0 ? x : find(e[x]); }
state is j, is aij = pij + k∈G aik pkj . The expected
P time until and compute max of intervals. Can be changed to other things. Use with a int time() { return sz(st); }
bump allocator for better performance, and SmallPtr or implicit indices to void rollback(int t) {
absorption, when the initial state is i, is ti = 1 + k∈G pki tk . for (int i = time(); i --> t;)
save memory.
Usage: Node* tr = new Node(v, 0, sz(v)); e[st[i].first] = st[i].second;
Time: O (log N ). st.resize(t);
}
Data structures (3) "../various/BumpAllocator.h"
ModMulLL.h } ll crt(ll a, ll m, ll b, ll n) {
Description: Calculate a·b mod c (or ab mod c) for 0 ≤ a, b ≤ c ≤ 7.2·1018 . for (int i : pr) isPrime[i] = 1; if (n > m) swap(a, b), swap(m, n);
Time: O (1) for modmul, O (log b) for modpow return pr; ll x, y, g = euclid(m, n, x, y);
bbbd8f, 11 lines } assert((a - b) % g == 0); // e l s e no solution
typedef unsigned long long ull; x = (b - a) % n * x % n / g * m + a;
ull modmul(ull a, ull b, ull M) { MillerRabin.h return x < 0 ? x + m*n/g : x;
ll ret = a * b - M * ull(1.L / M * a * b); Description: Deterministic Miller-Rabin primality test. Guaranteed to }
return ret + M * (ret < 0) - M * (ret >= (ll)M); work for numbers up to 7 · 1018 ; for larger numbers, use Python and ex-
} tend A randomly.
ull modpow(ull b, ull e, ull mod) { Time: 7 times the complexity of ab mod c. 5.3.1 Bézout’s identity
ull ans = 1; "ModMulLL.h" 60dcd1, 12 lines
for (; e; b = modmul(b, b, mod), e /= 2)
if (e & 1) ans = modmul(ans, b, mod);
bool isPrime(ull n) { For a 6=, b 6= 0, then d = gcd(a, b) is the smallest positive integer
if (n < 2 || n % 6 % 4 != 1) return (n | 1) == 3; for which there are integer solutions to
return ans;
ull A[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022},
}
s = __builtin_ctzll(n-1), d = n >> s;
for (ull a : A) { // ^ count t r a i l i n g zeroes
ax + by = d
ModSqrt.h ull p = modpow(a%n, d, n), i = s;
Description: Tonelli-Shanks algorithm for modular square roots. Finds x while (p != 1 && p != n - 1 && a % n && i--) If (x, y) is one solution, then all solutions are given by
s.t. x2 = a (mod p) (−x gives the other solution). p = modmul(p, p, n);
Time: O log2 p worst case, O (log p) for most p
if (p != n-1 && i != s) return 0; kb ka
"ModPow.h" 19a793, 24 lines } x+ ,y − , k∈Z
ll sqrt(ll a, ll p) { return 1;
gcd(a, b) gcd(a, b)
a %= p; if (a < 0) a += p; }
if (a == 0) return 0; phiFunction.h
assert(modpow(a, (p-1)/2, p) == 1); // e l s e no solution Factor.h Description: Euler’s φ function is defined as φ(n) := # of positive integers
if (p % 4 == 3) return modpow(a, (p+1)/4, p); Description: Pollard-rho randomized factorization algorithm. Returns ≤ n that are coprime with n. φ(1) = 1, p prime ⇒ φ(pk ) = (p − 1)pk−1 ,
// a^(n+3)/8 or 2^(n+3)/8 ∗ 2^(n−1)/4 works i f p % 8 == 5
ll s = p - 1, n = 2; ofa number, in arbitrary order (e.g. 2299 -> {11, 19, 11}).
prime factors k
m, n coprime ⇒ φ(mn) = φ(m)φ(n). If n = p1 1 p2 2 ...pk
k
r
r then φ(n) =
Time: O n1/4 , less for numbers with small factors. k1 −1 kr −1 Q
int r = 0, m; (p1 − 1)p1 ...(pr − 1)pr . φ(n) = n · p|n (1 − 1/p).
while (s % 2 == 0) "ModMulLL.h", "MillerRabin.h" a33cf6, 18 lines P P
d|n φ(d) = n, 1≤k≤n,gcd(k,n)=1 k = nφ(n)/2, n > 1
++r, s /= 2; ull pollard(ull n) {
while (modpow(n, (p - 1) / 2, p) != p - 1) ++n; auto f = [n](ull x) { return modmul(x, x, n) + 1; }; Euler’s thm: a, n coprime ⇒ aφ(n) ≡ 1 (mod n).
ll x = modpow(a, (s + 1) / 2, p); ull x = 0, y = 0, t = 30, prd = 2, i = 1, q; Fermat’s little thm: p prime ⇒ ap−1 ≡ 1 (mod p) ∀a. cf7d6d, 8 lines
ll b = modpow(a, s, p), g = modpow(n, s, p); while (t++ % 40 || __gcd(prd, n) == 1) {
const int LIM = 5000000;
for (;; r = m) { if (x == y) x = ++i, y = f(x);
int phi[LIM];
ll t = b; if ((q = modmul(prd, max(x,y) - min(x,y), n))) prd = q;
for (m = 0; m < r && t != 1; ++m) x = f(x), y = f(f(y));
void calculatePhi() {
t = t * t % p; }
rep(i,0,LIM) phi[i] = i&1 ? i : i/2;
if (m == 0) return x; return __gcd(prd, n);
for (int i = 3; i < LIM; i += 2) if(phi[i] == i)
ll gs = modpow(g, 1LL << (r - m - 1), p); }
for (int j = i; j < LIM; j += i) phi[j] -= phi[j] / i;
g = gs * gs % p; vector<ull> factor(ull n) {
}
x = x * gs % p; if (n == 1) return {};
KTH ContinuedFractions FracBinarySearch IntPerm 10
5.4 Fractions 5.5 Pythagorean Triples IntPerm.h
Description: Permutation -> integer conversion. (Not order preserving.)
The Pythagorean triples are uniquely generated by Integer -> permutation can use a lookup table.
Time: O (n) 044568, 6 lines
return btoa[b] = a, 1; Description: Finds a minimum vertex cover in a bipartite graph. The size vector<pii> generalMatching(int N, vector<pii>& ed) {
} is the same as the size of a maximum matching, and the complement is a vector<vector<ll>> mat(N, vector<ll>(N)), A;
return 0; maximum independent set. for (pii pa : ed) {
} "DFSMatching.h" da4196, 20 lines int a = pa.first, b = pa.second, r = rand() % mod;
vi cover(vector<vi>& g, int n, int m) { mat[a][b] = r, mat[b][a] = (mod - r) % mod;
int hopcroftKarp(vector<vi>& g, vi& btoa) { vi match(m, -1); }
int res = 0; int res = dfsMatching(g, match);
vi A(g.size()), B(btoa.size()), cur, next; vector<bool> lfound(n, true), seen(m); int r = matInv(A = mat), M = 2*N - r, fi, fj;
for (;;) { for (int it : match) if (it != -1) lfound[it] = false; assert(r % 2 == 0);
fill(all(A), 0); vi q, cover;
fill(all(B), 0); rep(i,0,n) if (lfound[i]) q.push_back(i); if (M != N) do {
cur.clear(); while (!q.empty()) { mat.resize(M, vector<ll>(M));
for (int a : btoa) if(a != -1) A[a] = -1; int i = q.back(); q.pop_back(); rep(i,0,N) {
rep(a,0,sz(g)) if(A[a] == 0) cur.push_back(a); lfound[i] = 1; mat[i].resize(M);
for (int lay = 1;; lay++) { for (int e : g[i]) if (!seen[e] && match[e] != -1) { rep(j,N,M) {
bool islast = 0; seen[e] = true; int r = rand() % mod;
next.clear(); q.push_back(match[e]); mat[i][j] = r, mat[j][i] = (mod - r) % mod;
KTH SCC BiconnectedComponents 2sat EulerWalk 14
} Usage: int eid = 0; ed.resize(N); j = max(2*j, -1-2*j);
} for each edge (a,b) { gr[f].push_back(j^1);
} while (matInv(A = mat) != M); ed[a].emplace back(b, eid); gr[j].push_back(f^1);
ed[b].emplace back(a, eid++); } }
vi has(M, 1); vector<pii> ret; bicomps([&](const vi& edgelist) {...}); void setValue(int x) { either(x, x); }
rep(it,0,M/2) { Time: O (E + V ) 2965e5, 33 lines
rep(i,0,M) if (has[i]) void atMostOne(const vi& li) { // ( optional )
rep(j,i+1,M) if (A[i][j] && mat[i][j]) { vi num, st; if (sz(li) <= 1) return;
fi = i; fj = j; goto done; vector<vector<pii>> ed; int cur = ∼li[0];
} assert(0); done: int Time; rep(i,2,sz(li)) {
if (fj < N) ret.emplace_back(fi, fj); template<class F> int next = addVar();
has[fi] = has[fj] = 0; int dfs(int at, int par, F& f) { either(cur, ∼li[i]);
rep(sw,0,2) { int me = num[at] = ++Time, e, y, top = me; either(cur, next);
ll a = modpow(A[fi][fj], mod-2); for (auto pa : ed[at]) if (pa.second != par) { either(∼li[i], next);
rep(i,0,M) if (has[i] && A[i][fj]) { tie(y, e) = pa; cur = ∼next;
ll b = A[i][fj] * a % mod; if (num[y]) { }
rep(j,0,M) A[i][j] = (A[i][j] - A[fi][j] * b) % mod; top = min(top, num[y]); either(cur, ∼li[1]);
} if (num[y] < me) }
swap(fi,fj); st.push_back(e);
} } else { vi val, comp, z; int time = 0;
} int si = sz(st); int dfs(int i) {
return ret; int up = dfs(y, e, f); int low = val[i] = ++time, x; z.push_back(i);
} top = min(top, up); for(int e : gr[i]) if (!comp[e])
if (up == me) { low = min(low, val[e] ?: dfs(e));
st.push_back(e); if (low == val[i]) do {
f(vi(st.begin() + si, st.end())); x = z.back(); z.pop_back();
7.4 DFS algorithms st.resize(si); comp[x] = low;
} if (values[x>>1] == -1)
else if (up < me) st.push_back(e); values[x>>1] = x&1;
SCC.h else { /∗ e i s a bridge ∗/ }
Description: Finds strongly connected components in a directed graph. If } while (x != i);
} return val[i] = low;
vertices u, v belong to the same component, we can reach u from v and vice }
versa. }
return top;
Usage: scc(graph, [&](vi& v) { ... }) visits all components }
in reverse topological order. comp[i] holds the component bool solve() {
index of a node (a component only has edges to components with values.assign(N, -1);
template<class F> val.assign(2*N, 0); comp = val;
lower index). ncomps will contain the number of components. void bicomps(F f) {
Time: O (E + V ) rep(i,0,2*N) if (!comp[i]) dfs(i);
76b5c9, 24 lines num.assign(sz(ed), 0); rep(i,0,N) if (comp[2*i] == comp[2*i+1]) return 0;
vi val, comp, z, cont; rep(i,0,sz(ed)) if (!num[i]) dfs(i, -1, f); return 1;
int Time, ncomps; } }
template<class G, class F> int dfs(int j, G& g, F& f) { };
int low = val[j] = ++Time, x; z.push_back(j); 2sat.h
for (auto e : g[j]) if (comp[e] < 0) Description: Calculates a valid assignment to boolean variables a,
low = min(low, val[e] ?: dfs(e,g,f)); b, c,... to a 2-SAT problem, so that an expression of the type
(akkb)&&(!akkc)&&(dkk!b)&&... becomes true, or reports that it is unsatis-
if (low == val[j]) { fiable. Negated variables are represented by bit-inversions (∼x).
do { Usage: TwoSat ts(number of boolean variables);
x = z.back(); z.pop_back(); ts.either(0, ∼3); // Var 0 is true or var 3 is false
EulerWalk.h
Description: Eulerian undirected/directed path/cycle algorithm. Input
comp[x] = ncomps; ts.setValue(2); // Var 2 is true
should be a vector of (dest, global edge index), where for undirected graphs,
cont.push_back(x); ts.atMostOne({0,∼1,2}); // <= 1 of vars 0, ∼1 and 2 are true
forward/backward edges have the same index. Returns a list of nodes in
} while (x != j); ts.solve(); // Returns true iff it is solvable
the Eulerian path/cycle with src at both start and end, or empty list if no
f(cont); cont.clear(); ts.values[0..N-1] holds the assigned values to the vars
cycle/path exists. To get edge indices back, add .second to s and ret.
ncomps++; Time: O (N + E), where N is the number of boolean variables, and E is the
Time: O (V + E) 780b64, 15 lines
} number of clauses. 5f9706, 56 lines
return val[j] = low; vi eulerWalk(vector<vector<pii>>& gr, int nedges, int src=0) {
} struct TwoSat {
int n = sz(gr);
template<class G, class F> void scc(G& g, F f) { int N;
vi D(n), its(n), eu(nedges), ret, s = {src};
vector<vi> gr;
int n = sz(g); D[src]++; // to allow Euler paths , not j u s t cycles
val.assign(n, 0); comp.assign(n, -1); vi values; // 0 = false , 1 = true
while (!s.empty()) {
Time = ncomps = 0; int x = s.back(), y, e, &it = its[x], end = sz(gr[x]);
rep(i,0,n) if (comp[i] < 0) dfs(i, g, f); TwoSat(int n = 0) : N(n), gr(2*n) {}
if (it == end){ ret.push_back(x); s.pop_back(); continue; }
} tie(y, e) = gr[x][it++];
int addVar() { // ( optional )
if (!eu[e]) {
gr.emplace_back();
D[x]--, D[y]++;
BiconnectedComponents.h gr.emplace_back();
eu[e] = 1; s.push_back(y);
Description: Finds all biconnected components in an undirected graph, and return N++;
}}
runs a callback for the edges in each. In a biconnected component there are }
for (int x : D) if (x < 0 || sz(ret) != nedges+1) return {};
at least two distinct paths between any two nodes. Note that a node can be
return {ret.rbegin(), ret.rend()};
in several components. An edge which is not in a component is a bridge, i.e., void either(int f, int j) {
}
not part of any cycle. f = max(2*f, -1-2*f);
KTH EdgeColoring MaximalCliques MaximumClique MaximumIndependentSet BinaryLifting LCA CompressTree 15
7.5 Coloring Time: Runs in about 1s for n=155 and worst case random graphs (p=.90). rep(i,1,d) rep(j,0,sz(P))
Runs faster for sparse graphs. f7c0bc, 49 lines
jmp[i][j] = jmp[i-1][jmp[i-1][j]];
return jmp;
EdgeColoring.h typedef vector<bitset<200>> vb; }
Description: Given a simple, undirected graph with max degree D, com- struct Maxclique {
putes a (D + 1)-coloring of the edges such that no neighboring edges share double limit=0.025, pk=0; int jmp(vector<vi>& tbl, int nod, int steps){
a color. (D-coloring is NP-hard, but can be done for bipartite graphs by struct Vertex { int i, d=0; }; rep(i,0,sz(tbl))
repeated matchings of max-degree nodes.) typedef vector<Vertex> vv; if(steps&(1<<i)) nod = tbl[i][nod];
Time: O (N M ) e210e2, 31 lines
vb e; return nod;
vv V; }
vi edgeColoring(int N, vector<pii> eds) { vector<vi> C;
vi cc(N + 1), ret(sz(eds)), fan(N), free(N), loc; vi qmax, q, S, old;
for (pii e : eds) ++cc[e.first], ++cc[e.second]; int lca(vector<vi>& tbl, vi& depth, int a, int b) {
void init(vv& r) { if (depth[a] < depth[b]) swap(a, b);
int u, v, ncols = *max_element(all(cc)) + 1; for (auto& v : r) v.d = 0;
vector<vi> adj(N, vi(ncols, -1)); a = jmp(tbl, a, depth[a] - depth[b]);
for (auto& v : r) for (auto j : r) v.d += e[v.i][j.i]; if (a == b) return a;
for (pii e : eds) { sort(all(r), [](auto a, auto b) { return a.d > b.d; });
tie(u, v) = e; for (int i = sz(tbl); i--;) {
int mxD = r[0].d; int c = tbl[i][a], d = tbl[i][b];
fan[0] = v; rep(i,0,sz(r)) r[i].d = min(i, mxD) + 1;
loc.assign(ncols, 0); if (c != d) a = c, b = d;
} }
int at = u, end = u, d, c = free[u], ind = 0, i = 0; void expand(vv& R, int lev = 1) {
while (d = free[v], !loc[d] && (v = adj[u][d]) != -1) return tbl[0][a];
S[lev] += S[lev - 1] - old[lev]; }
loc[d] = ++ind, cc[ind] = d, fan[ind] = v; old[lev] = S[lev - 1];
cc[loc[d]] = c; while (sz(R)) {
for (int cd = d; at != -1; cd ^= c ^ d, at = adj[at][cd]) if (sz(q) + R.back().d <= sz(qmax)) return; LCA.h
swap(adj[at][cd], adj[end = at][cd ^ c ^ d]); q.push_back(R.back().i); Description: Data structure for computing lowest common ancestors in a
while (adj[fan[i]][d] != -1) { vv T; tree (with 0 as root). C should be an adjacency list of the tree, either directed
int left = fan[i], right = fan[++i], e = cc[i]; for(auto v:R) if (e[R.back().i][v.i]) T.push_back({v.i}); or undirected.
adj[u][e] = left; if (sz(T)) { Time: O (N log N + Q)
adj[left][e] = u; if (S[lev]++ / ++pk < limit) init(T); "../data-structures/RMQ.h" 0f62fb, 21 lines
adj[right][e] = -1; int j = 0, mxk = 1, mnk = max(sz(qmax) - sz(q) + 1, 1); struct LCA {
free[right] = e; C[1].clear(), C[2].clear(); int T = 0;
} for (auto v : T) { vi time, path, ret;
adj[u][d] = fan[i]; int k = 1; RMQ<int> rmq;
adj[fan[i]][d] = u; auto f = [&](int i) { return e[v.i][i]; };
for (int y : {fan[0], u, end}) while (any_of(all(C[k]), f)) k++; LCA(vector<vi>& C) : time(sz(C)), rmq((dfs(C,0,-1), ret)) {}
for (int& z = free[y] = 0; adj[y][z] != -1; z++); if (k > mxk) mxk = k, C[mxk + 1].clear(); void dfs(vector<vi>& C, int v, int par) {
} if (k < mnk) T[j++].i = v.i; time[v] = T++;
rep(i,0,sz(eds)) C[k].push_back(v.i); for (int y : C[v]) if (y != par) {
for (tie(u, v) = eds[i]; adj[u][ret[i]] != v;) ++ret[i]; } path.push_back(v), ret.push_back(time[v]);
return ret; if (j > 0) T[j - 1].d = 0; dfs(C, y, v);
} rep(k,mnk,mxk + 1) for (int i : C[k]) }
T[j].i = i, T[j++].d = k; }
expand(T, lev + 1);
} else if (sz(q) > sz(qmax)) qmax = q;
7.6 Heuristics q.pop_back(), R.pop_back();
int lca(int a, int b) {
if (a == b) return a;
} tie(a, b) = minmax(time[a], time[b]);
MaximalCliques.h } return path[rmq.query(a, b)];
Description: Runs a callback for all maximal cliques in a graph (given as a vi maxClique() { init(V), expand(V); return qmax; } }
symmetric bitset matrix; self-edges not allowed). Callback is given a bitset Maxclique(vb conn) : e(conn), C(sz(e)+1), S(sz(C)), old(S) { // d i s t (a , b){return depth [ a ] + depth [ b ] − 2∗depth [ lca (a , b) ] ;}
representing rep(i,0,sz(e)) V.push_back({i}); };
themaximal clique. }
Time: O 3n/3 , much faster for sparse graphs
b0d5b1, 12 lines };
typedef bitset<128> B;
CompressTree.h
Description: Given a rooted tree and a subset S of nodes, compute the
template<class F> MaximumIndependentSet.h minimal subtree that contains all the nodes by adding all (at most |S| − 1)
void cliques(vector<B>& eds, F f, B P = ∼B(), B X={}, B R={}) { Description: To obtain a maximum independent set of a graph, find a max pairwise LCA’s and compressing edges. Returns a list of (par, orig index)
if (!P.any()) { if (!X.any()) f(R); return; } clique of the complement. If the graph is bipartite, see MinimumVertexCover. representing a tree rooted at 0. The root points to itself.
auto q = (P | X)._Find_first(); Time: O (|S| log |S|)
auto cands = P & ∼eds[q]; "LCA.h" 9775a0, 21 lines
rep(i,0,sz(eds)) if (cands[i]) {
R[i] = 1; 7.7 Trees typedef vector<pair<int, int>> vpi;
cliques(eds, f, P & eds[i], X & eds[i], R); vpi compressTree(LCA& lca, const vi& subset) {
R[i] = P[i] = 0; X[i] = 1; BinaryLifting.h static vi rev; rev.resize(sz(lca.time));
} Description: Calculate power of two jumps in a tree, to support fast upward vi li = subset, &T = lca.time;
} jumps and LCAs. Assumes the root node points to itself. auto cmp = [&](int a, int b) { return T[a] < T[b]; };
Time: construction O (N log N ), queries O (log N ) sort(all(li), cmp);
bfce85, 25 lines int m = sz(li)-1;
MaximumClique.h vector<vi> treeJump(vi& P){ rep(i,0,m) {
Description: Quickly finds a maximum clique of a graph (given as symmet- int on = 1, d = 1; int a = li[i], b = li[i+1];
ric bitset matrix; self-edges not allowed). Can be used to find a maximum while(on < sz(P)) on *= 2, d++; li.push_back(lca.lca(a, b));
independent set by finding a clique of the complement graph. vector<vi> jmp(d, P); }
KTH HLD LinkCutTree DirectedMST 16
sort(all(li), cmp); LinkCutTree.h }
li.erase(unique(all(li)), li.end()); Description: Represents a forest of unrooted trees. You can add and re- bool connected(int u, int v) { // are u, v in the same tree?
rep(i,0,sz(li)) rev[li[i]] = i; move edges (as long as the result is still a forest), and check whether two Node* nu = access(&node[u])->first();
vpi ret = {pii(0, li[0])}; nodes are in the same tree. return nu == access(&node[v])->first();
rep(i,0,sz(li)-1) { Time: All operations take amortized O (log N ). 5909e2, 90 lines
}
int a = li[i], b = li[i+1]; void makeRoot(Node* u) {
ret.emplace_back(rev[lca.lca(a, b)], b); struct Node { // Splay tree . Root ’ s pp contains tree ’ s parent . access(u);
} Node *p = 0, *pp = 0, *c[2]; u->splay();
return ret; bool flip = 0; if(u->c[0]) {
} Node() { c[0] = c[1] = 0; fix(); } u->c[0]->p = 0;
void fix() { u->c[0]->flip ^= 1;
if (c[0]) c[0]->p = this; u->c[0]->pp = u;
if (c[1]) c[1]->p = this; u->c[0] = 0;
HLD.h // (+ update sum of subtree elements etc . i f wanted) u->fix();
Description: Decomposes a tree into vertex disjoint heavy paths and light } }
edges such that the path from any leaf to the root contains at most log(n) void pushFlip() { }
light edges. Code does additive modifications and max queries, but can if (!flip) return; Node* access(Node* u) {
support commutative segtree modifications/queries on paths and subtrees. flip = 0; swap(c[0], c[1]); u->splay();
Takes as input the full adjacency list. VALS EDGES being true means that if (c[0]) c[0]->flip ^= 1; while (Node* pp = u->pp) {
values are stored in the edges, as opposed to the nodes. All values initialized if (c[1]) c[1]->flip ^= 1; pp->splay(); u->pp = 0;
to the segtree default. }
Root must be 0. if (pp->c[1]) {
Time: O (log N )2 int up() { return p ? p->c[1] == this : -1; } pp->c[1]->p = 0; pp->c[1]->pp = pp; }
"../data-structures/LazySegmentTree.h" 6f34db, 46 lines void rot(int i, int b) { pp->c[1] = u; pp->fix(); u = pp;
template <bool VALS_EDGES> struct HLD { int h = i ^ b; }
int N, tim = 0; Node *x = c[i], *y = b == 2 ? x : x->c[h], *z = b ? y : x; return u;
vector<vi> adj; if ((y->p = p)) p->c[up()] = y; }
vi par, siz, depth, rt, pos; c[i] = z->c[i ^ 1]; };
Node *tree; if (b < 2) {
x->c[h] = y->c[h ^ 1];
HLD(vector<vi> adj_)
z->c[h ^ 1] = b ? x : this; DirectedMST.h
: N(sz(adj_)), adj(adj_), par(N, -1), siz(N, 1), depth(N), Description: Finds a minimum spanning tree/arborescence of a directed
rt(N),pos(N),tree(new Node(0, N)){ dfsSz(0); dfsHld(0); } }
y->c[i ^ 1] = b ? this : x; graph, given a root node. If no MST exists, returns -1.
void dfsSz(int v) { Time: O (E log V )
if (par[v] != -1) adj[v].erase(find(all(adj[v]), par[v])); fix(); x->fix(); y->fix();
if (p) p->fix(); "../data-structures/UnionFindRollback.h" 39e620, 60 lines
for (int& u : adj[v]) {
swap(pp, y->pp); struct Edge { int a, b; ll w; };
par[u] = v, depth[u] = depth[v] + 1;
} struct Node {
dfsSz(u);
void splay() { Edge key;
siz[v] += siz[u];
for (pushFlip(); p; ) { Node *l, *r;
if (siz[u] > siz[adj[v][0]]) swap(u, adj[v][0]);
if (p->p) p->p->pushFlip(); ll delta;
}
p->pushFlip(); pushFlip(); void prop() {
}
int c1 = up(), c2 = p->up(); key.w += delta;
void dfsHld(int v) {
if (c2 == -1) p->rot(c1, 2); if (l) l->delta += delta;
pos[v] = tim++;
else p->p->rot(c2, c1 != c2); if (r) r->delta += delta;
for (int u : adj[v]) {
} delta = 0;
rt[u] = (u == adj[v][0] ? rt[v] : u);
} }
dfsHld(u);
Node* first() { Edge top() { prop(); return key; }
}
pushFlip(); };
}
return c[0] ? c[0]->first() : (splay(), this); Node *merge(Node *a, Node *b) {
template <class B> void process(int u, int v, B op) {
} if (!a || !b) return a ?: b;
for (; rt[u] != rt[v]; v = par[rt[v]]) {
}; a->prop(), b->prop();
if (depth[rt[u]] > depth[rt[v]]) swap(u, v);
if (a->key.w > b->key.w) swap(a, b);
op(pos[rt[v]], pos[v] + 1);
struct LinkCut { swap(a->l, (a->r = merge(b, a->r)));
}
vector<Node> node; return a;
if (depth[u] > depth[v]) swap(u, v);
LinkCut(int N) : node(N) {} }
op(pos[u] + VALS_EDGES, pos[v] + 1);
void pop(Node*& a) { a->prop(); a = merge(a->l, a->r); }
}
void modifyPath(int u, int v, int val) { void link(int u, int v) { // add an edge (u, v)
assert(!connected(u, v)); pair<ll, vi> dmst(int n, int r, vector<Edge>& g) {
process(u, v, [&](int l, int r) { tree->add(l, r, val); });
makeRoot(&node[u]); RollbackUF uf(n);
}
node[u].pp = &node[v]; vector<Node*> heap(n);
int queryPath(int u, int v) { // Modify depending on problem
} for (Edge e : g) heap[e.b] = merge(heap[e.b], new Node{e});
int res = -1e9;
process(u, v, [&](int l, int r) { void cut(int u, int v) { // remove an edge (u, v) ll res = 0;
Node *x = &node[u], *top = &node[v]; vi seen(n, -1), path(n), par(n);
res = max(res, tree->query(l, r));
makeRoot(top); x->splay(); seen[r] = r;
});
assert(top == (x->pp ?: x->c[0])); vector<Edge> Q(n), in(n, {-1,-1}), comp;
return res;
if (x->pp) x->pp = 0; deque<tuple<int, int, vector<Edge>>> cycs;
}
else { rep(s,0,n) {
int querySubtree(int v) { // modifySubtree i s similar
x->c[0] = top->p = 0; int u = s, qi = 0, w;
return tree->query(pos[v] + VALS_EDGES, pos[v] + siz[v]);
x->fix(); while (seen[u] < 0) {
}
} if (!heap[u]) return {-1,{}};
};
Edge e = heap[u]->top();
KTH Point lineDistance SegmentDistance SegmentIntersection lineIntersection sideOf OnSegment linearTransformation 17
heap[u]->delta -= e.w, pop(heap[u]); P operator-(P p) const { return P(x-p.x, y-p.y); } // Checks i f intersection i s single non−endpoint point .
Q[qi] = e, path[qi++] = u, seen[u] = s; P operator*(T d) const { return P(x*d, y*d); } if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0)
res += e.w, u = uf.find(e.a); P operator/(T d) const { return P(x/d, y/d); } return {(a * ob - b * oa) / (ob - oa)};
if (seen[u] == s) { T dot(P p) const { return x*p.x + y*p.y; } set<P> s;
Node* cyc = 0; T cross(P p) const { return x*p.y - y*p.x; } if (onSegment(c, d, a)) s.insert(a);
int end = qi, time = uf.time(); T cross(P a, P b) const { return (a-*this).cross(b-*this); } if (onSegment(c, d, b)) s.insert(b);
do cyc = merge(cyc, heap[w = path[--qi]]); T dist2() const { return x*x + y*y; } if (onSegment(a, b, c)) s.insert(c);
while (uf.join(u, w)); double dist() const { return sqrt((double)dist2()); } if (onSegment(a, b, d)) s.insert(d);
u = uf.find(u), heap[u] = cyc, seen[u] = -1; // angle to x−axis in interval [−pi , pi ] return {all(s)};
cycs.push_front({u, time, {&Q[qi], &Q[end]}}); double angle() const { return atan2(y, x); } }
} P unit() const { return *this/dist(); } // makes d i s t ()=1
} P perp() const { return P(-y, x); } // rotates +90 degrees
rep(i,0,qi) in[uf.find(Q[i].b)] = Q[i]; P normal() const { return perp().unit(); }
lineIntersection.h
Description:
} // returns point rotated ’a ’ radians ccw around the origin
If a unique intersection point of the lines going through s1,e1
P rotate(double a) const {
and s2,e2 exists {1, point} is returned. If no intersection point
for (auto& [u,t,comp] : cycs) { // restore s o l ( optional ) return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); }
exists {0, (0,0)} is returned and if infinitely many exists {-1, e2 r
uf.rollback(t); friend ostream& operator<<(ostream& os, P p) {
(0,0)} is returned. The wrong position will be returned if P
Edge inEdge = in[u]; return os << "(" << p.x << "," << p.y << ")"; }
is Point<ll> and the intersection point does not have inte- e1 s2
ger coordinates. Products of three coordinates are used in s1
for (auto& e : comp) in[uf.find(e.b)] = e; };
in[uf.find(inEdge.b)] = inEdge;
intermediate steps so watch out for overflow if using int or ll.
}
rep(i,0,n) par[i] = in[i].a;
lineDistance.h Usage: auto res = lineInter(s1,e1,s2,e2);
Description: if (res.first == 1)
return {res, par}; cout << "intersection point at " << res.second << endl;
Returns the signed distance between point p and the line con-
}
taining points a and b. Positive value on left side and negative "Point.h" a01f81, 8 lines
on right as seen from a towards b. a==b gives nan. P is sup-
res
template<class P>
posed to be Point<T> or Point3D<T> where T is e.g. double e p
7.8 Math or long long. It uses products in intermediate steps so watch
pair<int, P> lineInter(P s1, P e1, P s2, P e2) {
auto d = (e1 - s1).cross(e2 - s2);
out for overflow if using int or long long. Using Point3D will if (d == 0) // i f p a r a l l e l
7.8.1 Number of Spanning Trees always give a non-negative distance. For Point3D, call .dist s return {-(s1.cross(e1, s2) == 0), P(0, 0)};
on the result of the cross product. auto p = s2.cross(e1, e2), q = s2.cross(e2, s1);
Create an N × N matrix mat, and for each edge a → b ∈ G, do "Point.h" f6bf6b, 4 lines
return {1, (s1 * p + e1 * q) / d};
mat[a][b]--, mat[b][b]++ (and mat[b][a]--, template<class P> }
double lineDist(const P& a, const P& b, const P& p) {
mat[a][a]++ if G is undirected). Remove the ith row and return (double)(b-a).cross(p-a)/(b-a).dist();
column and take the determinant; this yields the number of } sideOf.h
Description: Returns where p is as seen from s towards e. 1/0/-1 ⇔ left/on
directed spanning trees rooted at i (if G is undirected, remove
e res p
line/right. If the optional argument eps is given 0 is returned if p is within
any row/column). SegmentDistance.h distance eps from the line. P is supposed to be Point<T> where T is e.g.
Description: double or long long. It uses products in intermediate steps so watch out for
Returns the shortest distance between point p and the line overflow if using int or long long.
7.8.2 Erdős–Gallai theorem segment from point s to e. s Usage: bool left = sideOf(p1,p2,q)==1;
Usage: Point<double> a, b(2,2), p(1,1); "Point.h" 3af81c, 9 lines
A simple graph with node degrees d1 ≥ · · · ≥ dn exists iff bool onSegment = segDist(a,b,p) < 1e-10;
"Point.h" 5c88f4, 6 lines
template<class P>
d1 + · · · + dn is even and for every k = 1 . . . n, typedef Point<double> P;
int sideOf(P s, P e, P p) { return sgn(s.cross(e, p)); }
bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); } auto oa = c.cross(d, a), ob = c.cross(d, b), typedef Point<double> P;
P operator+(P p) const { return P(x+p.x, y+p.y); } oc = a.cross(b, c), od = a.cross(b, d); P linearTransformation(const P& p0, const P& p1,
KTH Angle CircleIntersection CircleTangents CirclePolygonIntersection circumcircle MinimumEnclosingCircle InsidePolygon PolygonArea PolygonCenter 18
const P& q0, const P& q1, const P& r) { CircleTangents.h MinimumEnclosingCircle.h
P dp = p1-p0, dq = q1-q0, num(dp.cross(dq), dp.dot(dq)); Description: Finds the external tangents of two circles, or internal if r2 is Description: Computes the minimum circle that encloses a set of points.
return q0 + P((r-p0).cross(num), (r-p0).dot(num))/dp.dist2(); negated. Can return 0, 1, or 2 tangents – 0 if one circle contains the other (or Time: expected O (n)
} overlaps it, in the internal case, or if the circles are the same); 1 if the circles "circumcircle.h" 09dd0a, 17 lines
are tangent to each other (in which case .first = .second and the tangent line pair<P, double> mec(vector<P> ps) {
is perpendicular to the line between the centers). .first and .second give the
Angle.h tangency points at circle 1 and 2 respectively. To find the tangents of a circle
shuffle(all(ps), mt19937(time(0)));
Description: A class for ordering angles (as represented by int points and P o = ps[0];
with a point set r2 to 0. double r = 0, EPS = 1 + 1e-8;
a number of rotations around the origin). Useful for rotational sweeping.
"Point.h" b0153d, 13 lines rep(i,0,sz(ps)) if ((o - ps[i]).dist() > r * EPS) {
Sometimes also represents points or vectors.
Usage: vector<Angle> v = {w[0], w[0].t360() ...}; // sorted template<class P> o = ps[i], r = 0;
int j = 0; rep(i,0,n) { while (v[j] < v[i].t180()) ++j; } vector<pair<P, P>> tangents(P c1, double r1, P c2, double r2) { rep(j,0,i) if ((o - ps[j]).dist() > r * EPS) {
// sweeps j such that (j-i) represents the number of positively P d = c2 - c1; o = (ps[i] + ps[j]) / 2;
oriented triangles with vertices at 0 and i double dr = r1 - r2, d2 = d.dist2(), h2 = d2 - dr * dr; r = (o - ps[i]).dist();
0f0602, 35 lines
if (d2 == 0 || h2 < 0) return {}; rep(k,0,j) if ((o - ps[k]).dist() > r * EPS) {
struct Angle { vector<pair<P, P>> out; o = ccCenter(ps[i], ps[j], ps[k]);
int x, y; for (double sign : {-1, 1}) { r = (o - ps[i]).dist();
int t; P v = (d * dr + d.perp() * sqrt(h2) * sign) / d2; }
Angle(int x, int y, int t=0) : x(x), y(y), t(t) {} out.push_back({c1 + v * r1, c2 + v * r2}); }
Angle operator-(Angle b) const { return {x-b.x, y-b.y, t}; } } }
int half() const { if (h2 == 0) out.pop_back(); return {o, r};
assert(x || y); return out; }
return y < 0 || (y == 0 && x < 0); }
}
Angle t90() const { return {-y, x, t + (half() && x >= 0)}; }
Angle t180() const { return {-x, -y, t + half()}; }
8.3 Polygons
Angle t360() const { return {x, y, t + 1}; } CirclePolygonIntersection.h
}; Description: Returns the area of the intersection of a circle with a ccw InsidePolygon.h
bool operator<(Angle a, Angle b) { polygon. Description: Returns true if p lies within the polygon. If strict is true, it
// add a . dist2 () and b . dist2 () to also compare distances Time: O (n) returns false for points on the boundary. The algorithm uses products in
return make_tuple(a.t, a.half(), a.y * (ll)b.x) < "../../content/geometry/Point.h" a1ee63, 19 lines intermediate steps so watch out for overflow.
make_tuple(b.t, b.half(), a.x * (ll)b.y); Usage: vector<P> v = {P{4,4}, P{1,2}, P{2,1}};
typedef Point<double> P;
} bool in = inPolygon(v, P{3, 3}, false);
#define arg(p, q) atan2(p.cross(q), p.dot(q))
Time: O (n)
double circlePoly(P c, double r, vector<P> ps) {
// Given two points , t h i s calculates the smallest angle between auto tri = [&](P p, P q) {
"Point.h", "OnSegment.h", "SegmentDistance.h" 2bf504, 11 lines
// them, i . e . , the angle that covers the defined l i n e segment . auto r2 = r * r / 2; template<class P>
pair<Angle, Angle> segmentAngles(Angle a, Angle b) { P d = q - p; bool inPolygon(vector<P> &p, P a, bool strict = true) {
if (b < a) swap(a, b); auto a = d.dot(p)/d.dist2(), b = (p.dist2()-r*r)/d.dist2(); int cnt = 0, n = sz(p);
return (b < a.t180() ? auto det = a * a - b; rep(i,0,n) {
make_pair(a, b) : make_pair(b, a.t360())); if (det <= 0) return arg(p, q) * r2; P q = p[(i + 1) % n];
} auto s = max(0., -a-sqrt(det)), t = min(1., -a+sqrt(det)); if (onSegment(p[i], q, a)) return !strict;
Angle operator+(Angle a, Angle b) { // point a + vector b if (t < 0 || 1 <= s) return arg(p, q) * r2; //or : i f ( segDist (p [ i ] , q , a) <= eps) return ! s t r i c t ;
Angle r(a.x + b.x, a.y + b.y, a.t); P u = p + d * s, v = p + d * t; cnt ^= ((a.y<p[i].y) - (a.y<q.y)) * a.cross(p[i], q) > 0;
if (a.t180() < r) r.t--; return arg(p,u) * r2 + u.cross(v)/2 + arg(v,q) * r2; }
return r.t180() < a ? r.t360() : r; }; return cnt;
} auto sum = 0.0; }
Angle angleDiff(Angle a, Angle b) { // angle b − angle a rep(i,0,sz(ps))
int tu = b.t - a.t; a.t = b.t;
return {a.x*b.x + a.y*b.y, a.x*b.y - a.y*b.x, tu - (b < a)};
sum += tri(ps[i] - c, ps[(i + 1) % sz(ps)] - c); PolygonArea.h
return sum; Description: Returns twice the signed area of a polygon. Clockwise enu-
} } meration gives negative area. Watch out for overflow if using int as T!
"Point.h" f12300, 6 lines
template<class T>
8.2 Circles T polygonArea2(vector<Point<T>>& v) {
circumcircle.h T a = v.back().cross(v[0]);
Description:
CircleIntersection.h B rep(i,0,sz(v)-1) a += v[i].cross(v[i+1]);
Description: Computes the pair of points at which two circles intersect. The circumcirle of a triangle is the circle intersecting all return a;
Returns false in case of no intersection. three vertices. ccRadius returns the radius of the circle going r c }
"Point.h" 84d6d3, 11 lines through points A, B and C and ccCenter returns the center C
of the same circle. A
typedef Point<double> P;
"Point.h" 1caa3a, 9 lines
PolygonCenter.h
bool circleInter(P a,P b,double r1,double r2,pair<P, P>* out) { Description: Returns the center of mass for a polygon.
if (a == b) { assert(r1 != r2); return false; } typedef Point<double> P; Time: O (n)
P vec = b - a; double ccRadius(const P& A, const P& B, const P& C) { "Point.h" 9706dc, 9 lines
double d2 = vec.dist2(), sum = r1+r2, dif = r1-r2, return (B-A).dist()*(C-B).dist()*(A-C).dist()/
typedef Point<double> P;
p = (d2 + r1*r1 - r2*r2)/(d2*2), h2 = r1*r1 - p*p*d2; abs((B-A).cross(C-A))/2;
P polygonCenter(const vector<P>& v) {
if (sum*sum < d2 || dif*dif > d2) return false; }
P res(0, 0); double A = 0;
P mid = a + vec*p, per = vec.perp() * sqrt(fmax(0, h2) / d2); P ccCenter(const P& A, const P& B, const P& C) {
for (int i = 0, j = sz(v) - 1; i < sz(v); j = i++) {
*out = {mid + per, mid - per}; P b = C-A, c = B-A;
res = res + (v[i] + v[j]) * v[j].cross(v[i]);
return true; return A + (b*c.dist2()-c*b.dist2()).perp()/b.cross(c)/2;
A += v[j].cross(v[i]);
} }
}
KTH PolygonCut ConvexHull HullDiameter PointInsideHull LineHullIntersection ClosestPair kdTree 19
return res / A / 3; Time: O (log N ) 8.4 Misc. Point Set Problems
} "Point.h", "sideOf.h", "OnSegment.h" 71446b, 14 lines
SIMD.h
Description: Cheat sheet of SSE/AVX intrinsics, for doing arithmetic
on several numbers at once. Can provide a constant factor improvement
of about 4, orthogonal to loop unrolling. Operations follow the pat-
tern " mm(256)? name (si(128|256)|epi(8|16|32|64)|pd|ps)". Not all
are described here; grep for mm in /usr/lib/gcc/*/4.9/include/ for
more. If AVX is unsupported, try 128-bit operations, ”emmintrin.h” and
#define SSE and MMX before including it. For aligned memory use
mm malloc(size, 32) or int buf[N] alignas(32), but prefer loadu/s-
toreu. 551b82, 43 lines
// High−l e v e l / s p e c i f i c methods :
// load (u)? si256 , store (u)? si256 , setzero si256 , mm malloc
// blendv ( epi8 | ps | pd) ( z?y : x) , movemask epi8 ( h i b i t s of bytes )
// i32gather epi32 (addr , x , 4) : map addr [ ] over 32−b parts of x
// sad epu8 : sum of absolute differences of u8, outputs 4xi64
// maddubs epi16 : dot product of unsigned i7 ’ s , outputs 16xi15
// madd epi16 : dot product of signed i16 ’ s , outputs 8xi32
// extractf128 si256 ( , i ) (256−>128) , cvtsi128 si32 (128−>lo32 )
// permute2f128 si256(x , x ,1) swaps 128−b i t lanes
// shuffle epi32 (x , 3∗64+2∗16+1∗4+0) == x for each lane
// s h u f f l e e p i 8 (x , y) takes a vector instead of an imm