<<

University of Bergen Garbage Collectors Davide Pallotti, Jan Soukup, Olav Røthe Bakken

NWERC 2017 Nov 8, 2017 UiB template .bashrc .vimrc troubleshoot 1 tan v + tan w Contest (1) Any possible infinite ? tan(v + w) = Invalidated pointers or iterators? 1 − tan v tan w template.cpp Are you using too much memory? v + w v − w 15 lines Debug with resubmits (e.g. remapped signals, see Various). sin v + sin w = 2 sin cos #include 2 2 using namespace std; Time limit exceeded: v + w v − w Do you have any possible infinite loops? cos v + cos w = 2 cos cos #define rep(i, a, b) for(int i = a; i < (b); ++i) What is the complexity of your algorithm? 2 2 #define trav(a, x) for(auto& a : x) Are you copying a lot of unnecessary data? (References) #define all(x) x.begin(), x.end() How big is the input and output? (consider scanf) (V + W ) tan(v − w)/2 = (V − W ) tan(v + w)/2 #define sz(x) (int)(x).size() Avoid vector, map. (use arrays/unordered_map) typedef long long ll; What do your team mates think about your algorithm? where V,W are lengths of sides opposite angles v, w. typedef pair pii; typedef vector vi; Memory limit exceeded: a cos x + b sin x = r cos(x − φ) What is the max amount of memory your algorithm should need? int main() { Are you clearing all datastructures between test cases? a sin x + b cos x = r sin(x + φ) cin.sync_with_stdio(0); cin.tie(0); cin.exceptions(cin.failbit); √ 2 2 } Mathematics (2) where r = a + b , φ = atan2(b, a).

.bashrc 3 lines 2.1 Equations 2.4 Geometry alias =’g++ -Wall -Wconversion -Wfatal-errors -g -std=c++14 \ √ -fsanitize=undefined,address’ 2 2.4.1 Triangles 2 −b ± b − 4ac xmodmap -e ’clear lock’ -e ’keycode 66=less greater’ #caps = <> ax + bx + c = 0 ⇒ x = 2a Side lengths: a, b, c .vimrc a + b + c 2 lines The extremum is given by x = −b/2a. Semiperimeter: p = set cin aw ai is ts=4 sw=4 tm=50 nu noeb bg=dark ru cul 2 sy on | im jk | im kj | no ; : Area: A = pp(p − a)(p − b)(p − c) ed − bf abc troubleshoot.txt x = Circumradius: R = 52 lines ax + by = e ad − bc ⇒ 4A Pre-submit: cx + dy = f af − ec A Write a few simple test cases, if sample is not enough. y = Inradius: r = Are time limits close? If so, generate max cases. ad − bc p Is the memory usage fine? Length of median (divides√ triangle into two equal-area Could anything overflow? In general, given an equation Ax = b, the solution to a 1 2 2 2 Make sure to submit the right file. triangles): ma = 2 2b + 2c − a variable xi is given by Length of bisector (divides angles in two): Wrong answer: v Print your solution! Print debug output, as well. 0 u " 2# det Ai  a  Are you clearing all datastructures between test cases? x = u i sa = tbc 1 − Can your algorithm handle the whole range of input? det A b + c Read the full problem statement again. 0 Do you handle all corner cases correctly? where Ai is A with the i’th column replaced by b. sin α sin β sin γ 1 Have you understood the problem correctly? Law of sines: = = = Any uninitialized variables? a b c 2R 2.2 Recurrences 2 2 2 Any overflows? Law of cosines: a = b + c − 2bc cos α Confusing N and M, i and j, etc.? α + β Are you sure your algorithm works? If an = c1an−1 + ··· + ckan−k, and r1, . . . , rk are distinct a + b tan What special cases have you not thought of? roots of xk + c xk−1 + ··· + c , there are d , . . . , d s.t. Law of tangents: = 2 Are you sure the STL functions you use work as you think? 1 k 1 k a − b α − β Add some assertions, maybe resubmit. n n tan Create some testcases to run your algorithm on. an = d1r1 + ··· + dkrk . 2 Go through the algorithm for a simple case. Go through this list again. Non-distinct roots r become polynomial factors, e.g. 2.4.2 Quadrilaterals Explain your algorithm to a team mate. n Ask the team mate to look at your code. an = (d1n + d2)r . Go for a small walk, e.g. to the toilet. With side lengths a, b, c, d, diagonals e, f, diagonals angle θ, Is your output format correct? (including whitespace) area A and magic flux F = b2 + d2 − a2 − c2: Rewrite your solution from the start or let a team mate do it. 2.3 Trigonometry

Runtime error: p 2 2 2 Have you tested all corner cases locally? sin(v + w) = sin v cos w + cos v sin w 4A = 2ef · sin θ = F tan θ = 4e f − F 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? For cyclic quadrilaterals the sum of opposite angles is 180◦, Any assertions that might fail? p Any possible division by 0? (mod 0 for example) ef = ac + bd, and A = (p − a)(p − b)(p − c)(p − d). UiB 2 2.4.3 Spherical coordinates 2.7 First success distribution z x2 x3 ex = 1 + x + + + ..., (−∞ < x < ∞) The number of trials needed to get the first success in r 2! 3! y independent yes/no experiments, each wich yields success x2 x3 x4 with probability p is Fs(p), 0 ≤ p ≤ 1. ln(1 + x) = x − + − + ..., (−1 < x ≤ 1) 2 3 4 x p(k) = p(1 − p)k−1, k = 1, 2,... √ x x2 2x3 5x4 1 + x = 1 + − + − + ..., (−1 ≤ x ≤ 1) 2 8 32 128 1 1 − p p µ = , σ2 = x = r sin θ cos φ r = x2 + y2 + z2 2 x3 x5 x7 p p y = r sin θ sin φ θ = acos(z/px2 + y2 + z2) sin x = x − + − + ..., (−∞ < x < ∞) 3! 5! 7! z = r cos θ φ = atan2(y, x) Poisson distribution x2 x4 x6 cos x = 1 − + − + ..., (−∞ < x < ∞) 2.5 Derivatives/Integrals 2! 4! 6! The of events occurring in a fixed period of time t if these events occur with a known average rate κ and 2.8 Probability theory independently of the time since the last event is d 1 d 1 arcsin x = √ arccos x = −√ Let X be a discrete random variable with probability p (x) Po(λ), λ = tκ. dx 1 − x2 dx 1 − x2 X of assuming the value x. It will then have an expected value k d 2 d 1 P −λ λ tan x = 1 + tan x arctan x = (mean) µ = E(X) = x xpX (x) and variance p(k) = e , k = 0, 1, 2,... dx dx 1 + x2 2 2 2 P 2 k! σ = V (X) = E(X ) − (E(X)) = (x − E(X)) pX (x) Z ln | cos ax| Z sin ax − ax cos ax x tan ax = − x sin ax = where σ is the standard deviation. If X is instead 2 2 µ = λ, σ = λ a a continuous it will have a probability density function fX (x) √ ax Z 2 π Z e and the sums above will instead be integrals with p (x) e−x = erf(x) xeaxdx = (ax − 1) X 2 a2 replaced by fX (x). 2.8.2 Continuous distributions Expectation is linear: Uniform distribution Integration by parts: E(aX + bY ) = aE(X) + bE(Y ) If the probability density function is constant between a and Z b Z b b 0 b and 0 elsewhere it is U(a, b), a < b. f(x)g(x)dx = [F (x)g(x)]a − F (x)g (x)dx For independent X and Y , a a  1 a < x < b V (aX + bY ) = a2V (X) + b2V (Y ). f(x) = b−a 2.6 Sums 0 otherwise

b+1 a 2 a a+1 b c − c 2.8.1 Discrete distributions a + b (b − a) c + c + ··· + c = , c 6= 1 µ = , σ2 = c − 1 Binomial distribution 2 12

n(n + 1) The number of successes in n independent yes/no Exponential distribution 1 + 2 + 3 + ··· + n = 2 experiments, each which yields success with probability p is n(2n + 1)(n + 1) Bin(n, p), n = 1, 2,..., 0 ≤ p ≤ 1. The time between events in a Poisson process is 12 + 22 + 32 + ··· + n2 = Exp(λ), λ > 0. 6 n n2(n + 1)2 p(k) = pk(1 − p)n−k 13 + 23 + 33 + ··· + n3 =  λe−λx x ≥ 0 k f(x) = 4 0 x < 0 n(n + 1)(2n + 1)(3n2 + 3n − 1) 14 + 24 + 34 + ··· + n4 = µ = np, σ2 = np(1 − p) 30 1 1 µ = , σ2 = Bin(n, p) is approximately Po(np) for small p. λ λ2 UiB OrderStatisticTree SegmentTree LazySegmentTree UnionFind SubMatrix 3

Normal distribution OrderStatisticTree.h struct Node { Description: A set (not multiset!) with support for finding the n’th ele- Node *l = 0, *r = 0; ment, and finding the index of an element. int lo, hi, mset = inf, madd = 0, val = -inf; 2 Time: O (log N) Node(int lo,int hi):lo(lo),hi(hi){} // Large interval of −inf Most real random values with mean µ and variance σ are 16 lines 2 Node(vi& v, int lo, int hi) : lo(lo), hi(hi) { well described by N (µ, σ ), σ > 0. #include if (lo + 1 < hi) { using namespace __gnu_pbds; int mid = lo + (hi - lo)/2; 2 l = new Node(v, lo, mid); r = new Node(v, mid, hi); 1 − (x−µ) template f(x) = √ e 2σ2 val = max(l->val, r->val); 2πσ2 using Tree = tree, rb_tree_tag, } tree_order_statistics_node_update>; else val = v[lo]; } 2 2 void example() { If X1 ∼ N (µ1, σ1) and X2 ∼ N (µ2, σ2) then int query(int L, int R) { Tree 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; 2 2 2 2 assert(it == t.lower_bound(9)); aX1 + bX2 + c ∼ N (µ1 + µ2 + c, a σ1 + b σ2) push(); assert(t.order_of_key(10) == 1); return max(l->query(L, R), r->query(L, R)); assert(t.order_of_key(11) == 2); } assert(*t.find_by_order(0) == 8); void set(int L, int R, int x) { 2.9 Markov chains 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 { A Markov chain is a discrete random process with the SegmentTree.h push(), l->set(L, R, x), r->set(L, R, x); property that the next state depends only on the current val = max(l->val, r->val); Description: Zero-indexed max-tree. Bounds are inclusive to the left and } exclusive to the right. Can be changed by modifying T, LOW and f. state. Let X1,X2,... be a of random variables } Time: O (log N). generated by the Markov process. Then there is a transition 31 lines void add(int L, int R, int x) { struct Tree { if (R <= lo || hi <= L) return; matrix P = (pij), with pij = Pr(Xn = i|Xn−1 = j), and typedef int T; if (L <= lo && hi <= R) { p(n) = Pnp(0) is the probability distribution for X (i.e., const T LOW = -1234567890; if (mset != inf) mset += x; n else madd += x; (n) T f(T a, T b) { return max(a, b); } (0) val += x; pi = Pr(Xn = i)), where p is the initial distribution. int n; } vi s; else { Tree() {} push(), l->add(L, R, x), r->add(L, R, x); π is a stationary distribution if π = πP. If the Markov chain Tree(int m, T def=0) { init(m, def); } val = max(l->val, r->val); void init(int m, T def) { } is irreducible (it is possible to get to any state from any } 1 n = 1; while (n < m) n *= 2; state), then πi = where (Ti) is the expected time s.assign(n + m, def); void push() { E(Ti) E s.resize(2 * n, LOW); if (!l) { between two visits in state i. πj/πi is the expected number for (int i = n; i --> 1; ) int mid = lo + (hi - lo)/2; of visits in state j between two visits in state i. s[i] = f(s[i * 2], s[i*2 + 1]); l = new Node(lo, mid); r = new Node(mid, hi); } } void update(int pos, T val) { if (mset != inf) For a connected, undirected and non-bipartite graph, where pos += n; l->set(lo,hi,mset), r->set(lo,hi,mset), mset = inf; else if (madd) the transition probability is uniform among all neighbors, πi s[pos] = val; l->add(lo,hi,madd), r->add(lo,hi,madd), madd = 0; is proportional to node i’s degree. for (pos /= 2; pos >= 1; pos /= 2) s[pos] = f(s[pos * 2], s[pos * 2 + 1]); } } }; A Markov chain is ergodic if the asymptotic distribution is T query(int l, int r) { return que(1, l, r, 0, n); } T que(int pos, int l, int r, int lo, int hi) { independent of the initial distribution. A finite Markov if (r <= lo || hi <= l) return LOW; chain is ergodic iff it is irreducible and aperiodic (i.e., the if (l <= lo && hi <= r) return s[pos]; UnionFind.h gcd of cycle lengths is 1). lim Pk = 1π. int m = (lo + hi) / 2; Description: Disjoint-set data structure. k→∞ return f(que(2 pos, l, r, lo, m), Time: O (α(N)) * 13 lines que(2 * pos + 1, l, r, m, hi)); A Markov chain is an A-chain if the states can be } struct UF { }; vi e; partitioned into two sets A and G, such that all states in A UF(int n) : e(n, -1) {} bool same_set(int a, int b) { return find(a) == find(b); } are absorbing (pii = 1), and all states in G leads to an LazySegmentTree.h int size(int x) { return -e[find(x)]; } absorbing state in A. The probability for absorption in state Description: Segment tree with ability to add or set values of large in- int find(int x) { return e[x] < 0 ? x : e[x] = find(e[x]); } P void join(int a, int b) { i ∈ A, when the initial state is j, is aij = pij + k∈G aikpkj. tervals, and compute max of intervals. Can be changed to other things. Use with a bump allocator for better performance, and SmallPtr or implicit a = find(a), b = find(b); The expected time until absorption, when the initial state is indices to save memory. if (a == b) return; P if (e[a] > e[b]) swap(a, b); i, is ti = 1 + k∈G pkitk. Usage: Node* tr = new Node(v, 0, sz(v)); Time: O (log N). e[a] += e[b]; e[b] = a; "../various/BumpAllocator.h" 50 lines } }; Data structures (3) const int inf = 1e9; UiB Matrix LineContainer Treap FenwickTree FenwickTree2d 4

SubMatrix.h // (for doubles, use inf = 1/.0, div(a,b) = a/b) } Description: Calculate submatrix sums quickly, given upper-left and const ll inf = LLONG_MAX; } lower-right corners (half-open). ll div(ll a, ll b) { // floored division Usage: SubMatrix m(matrix); return a / b - ((a ˆ b) < 0 && a % b); } Node* ins(Node* t, Node* n, int pos) { m.sum(0, 0, 2, 2); // top left 4 elements bool isect(iterator x, iterator y) { auto pa = split(t, pos); Time: O N 2 + Q if (y == end()) { x->p = inf; return false;} return merge(merge(pa.first, n), pa.second); 13 lines if (x->k == y->k) x->p = x->m > y->m ? inf : -inf; } template else x->p = div(y->m - x->m, x->k - y->k); struct SubMatrix { return x->p >= y->p; // Example application: move the range [l, r) to index k vector> p; } void move(Node*& t, int l, int r, int k) { SubMatrix(vector>& v) { void add(ll k, ll m) { Node *a, *b, *c; int R = sz(v), C = sz(v[0]); auto z = insert({k, m, 0}), y = z++, x = y; tie(a,b) = split(t, l); tie(b,c) = split(b, r - l); p.assign(R+1, vector(C+1)); while (isect(y, z)) z = erase(z); if (k <= l) t = merge(ins(a, b, k), c); rep(r,0,R) rep(c,0,C) if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); else t = merge(a, ins(c, b, k - r)); p[r+1][c+1] = v[r][c] + p[r][c+1] + p[r+1][c] - p[r][c]; while ((y = x) != begin() && (--x)->p >= y->p) } } isect(x, erase(y)); T sum(int u, int l, int d, int r) { } return p[d][r] - p[d][l] - p[u][r] + p[u][l]; ll query(ll x) { FenwickTree.h } assert(!empty()); Description: Computes partial sums a[0] + a[1] + ... + a[pos - 1], and }; Q = 1; auto l = *lower_bound({0,0,x}); Q = 0; updates single elements a[i], taking the difference between the old and new return l.k * x + l.m; value. Time: Both operations are O (log N). Matrix.h } 22 lines }; Description: Basic operations on square matrices. struct FT { Usage: Matrix A; vector s; A.d = {{{{1,2,3}}, {{4,5,6}}, {{7,8,9}}}}; Treap.h FT(int n) : s(n) {} vector int vec = 1,2,3 ; void update(int pos, ll dif) { < > { } Description: A short self-balancing tree. It acts as a sequential container // a[pos] += dif vec = (AˆN) vec; for (; pos < sz(s); pos |= pos + 1) s[pos] += dif; * 26 lines with log-time splits/joins, and is easy to augment with additional data. } Time: O (log N) template struct Matrix { 55 lines ll query(int pos) { // sum of values in [0, pos) typedef Matrix M; struct Node { ll res = 0; array, N> d{}; Node *l = 0, *r = 0; for (; pos > 0; pos &= pos - 1) res += s[pos-1]; M operator*(const M& m) const { int val, y, c = 1; return res; M a; Node(int val) : val(val), y(rand()) {} } rep(i,0,N) rep(j,0,N) void recalc(); int lower_bound(ll sum) {// min pos st sum of [0, pos] >= sum rep(k,0,N) a.d[i][j] += d[i][k]*m.d[k][j]; }; // Returns n if no sum is >= sum, or −1 i f empty sum is . return a; if (sum <= 0) return -1; } int cnt(Node* n) { return n ? n->c : 0; } int pos = 0; vector operator*(const vector& vec) const { void Node::recalc() { c = cnt(l) + cnt(r) + 1; } for (int pw = 1 << 25; pw; pw >>= 1) { vector ret(N); if (pos + pw <= sz(s) && s[pos + pw-1] < sum) rep(i,0,N) rep(j,0,N) ret[i] += d[i][j] vec[j]; * template void each(Node* n, F f) { pos += pw, sum -= s[pos-1]; return ret; if (n) { each(n->l, f); f(n->val); each(n->r, f); } } } } return pos; M operatorˆ(ll p) const { } assert(p >= 0); pair split(Node* n, int k) { }; M a, b(*this); if (!n) return {}; rep(i,0,N) a.d[i][i] = 1; if (cnt(n->l) >= k) { // ”n−>val >= v” for lower bound(v) while (p) { auto pa = split(n->l, k); FenwickTree2d.h if (p&1) a = a*b; n->l = pa.second; Description: Computes sums a[i,j] for all irecalc(); ements a[i,j]. Requires that the elements to be updated are known in advance p >>= 1; return {pa.first, n}; (call fakeUpdate() before init()). 2  } } else { Time: O log N . (Use persistent segment trees for O (log N).) return a; auto pa = split(n->r, k - cnt(n->l) - 1); "FenwickTree.h" 22 lines } n->r = pa.first; struct FT2 { }; n->recalc(); vector ys; vector ft; return {n, pa.second}; FT2(int limx) : ys(limx) {} LineContainer.h } void fakeUpdate(int x, int y) { Description: Container where you can add lines of the form kx+m, and } for (; x < sz(ys); x |= x + 1) ys[x].push_back(y); query maximum values at points x. Useful for dynamic programming. } Time: O (log N) Node* merge(Node* l, Node* r) { void init() { 32 lines if (!l) return r; trav(v, ys) sort(all(v)), ft.emplace_back(sz(v)); bool Q; if (!r) return l; } struct Line { if (l->y > r->y) { int ind(int x, int y) { mutable ll k, m, p; l->r = merge(l->r, r); return (int)(lower_bound(all(ys[x]), y) - ys[x].begin()); } bool operator<(const Line& o) const { l->recalc(); void update(int x, int y, ll dif) { return Q ? p < o.p : k < o.k; return l; for (; x < sz(ys); x |= x + 1) } } else { ft[x].update(ind(x, y), dif); }; r->l = merge(l, r->l); } r->recalc(); ll query(int x, int y) { struct LineContainer : multiset { return r; ll sum = 0; UiB RMQ Polynomial BinarySearch GoldenSectionSearch PolyRoots PolyInterpolate HillClimbing Integrate IntegrateAdaptive 5

for (; x; x &= x - 1) //for(int i = 0; i < 60; ++i ){ PolyInterpolate.h sum += ft[x-1].query(ind(x-1, y)); while (b-a > 1e-6) { Description: Given n points (x[i], y[i]), computes an n-1-degree polyno- return sum; double m = (a+b)/2; mial p that passes through them: p(x) = a[0] ∗ x0 + ... + a[n − 1] ∗ xn−1. For } if (f(m) > 0) b = m; numerical precision, pick x[k] = c ∗ cos(k/(n − 1) ∗ π), k = 0 . . . n − 1. }; else a = m; Time: O n2 } 13 lines return a; typedef vector vd; RMQ.h } vd interpolate(vd x, vd y, int n) { Description: Range Minimum Queries on an array. Returns min(V[a], V[a vd res(n), temp(n); + 1], ... V[b - 1]) in constant time. Set inf to something reasonable before rep(k,0,n-1) rep(i,k+1,n) use. y[i] = (y[i] - y[k]) / (x[i] - x[k]); Usage: RMQ rmq(values); GoldenSectionSearch.h double last = 0; temp[0] = 1; rmq.query(inclusive, exclusive); Description: Finds the argument minimizing the function f in the in- rep(k,0,n) rep(i,0,n) { Time: O (|V | log |V | + Q) terval [a, b] assuming f is unimodal on the interval, i.e. has only one local 21 lines res[i] += y[k] * temp[i]; minimum. The maximum error in the result is eps. Works equally well for const int inf = numeric_limits::max(); swap(last, temp[i]); maximization with a small change in the code. See TernarySearch.h in the temp[i] -= last * x[k]; Various chapter for a discrete version. template } Usage: double func(double x) { return 4+x+.3*x*x; } struct RMQ { return res; double xmin = gss(-1000,1000,func); } vector> jmp; Time: O (log((b − a)/)) 14 lines RMQ(const vector& V) { double gss(double a, double b, double (*f)(double)) { HillClimbing.h int N = sz(V), on = 1, depth = 1; double r = (sqrt(5)-1)/2, eps = 1e-7; Description: Poor man’s optimization for unimodal functions. while (on < sz(V)) on *= 2, depth++; double x1 = b - r*(b-a), x2 = a + r*(b-a); 16 lines jmp.assign(depth, V); double f1 = f(x1), f2 = f(x2); typedef array P; rep(i,0,depth-1) rep(j,0,N) while (b-a > eps) jmp[i+1][j] = min(jmp[i][j], if (f1 < f2) { //change to > to find maximum double func(P p); jmp[i][min(N - 1, j + (1 << i))]); b = x2; x2 = x1; f2 = f1; } x1 = b - r*(b-a); f1 = f(x1); pair hillClimb(P start) { } else { pair cur(func(start), start); T query(int a, int b) { a = x1; x1 = x2; f1 = f2; for (double jmp = 1e9; jmp > 1e-20; jmp /= 2) { if (b <= a) return inf; x2 = a + r*(b-a); f2 = f(x2); rep(j,0,100) rep(dx,-1,2) rep(dy,-1,2) { int dep = 31 - __builtin_clz(b - a); } P p = cur.second; return min(jmp[dep][a], jmp[dep][b - (1 << dep)]); return a; p[0] += dx*jmp; } } p[1] += dy*jmp; }; cur = min(cur, make_pair(func(p), p)); } } PolyRoots.h return cur; Numerical (4) Description: Finds the real roots to a polynomial. } Usage: vector roots; Polynomial p(2); p.a[0] = 2; p.a[1] = -3; p.a[2] = 1; Polynomial.h 18 lines poly roots(p,-1e10,1e10,roots); // xˆ2-3x+2=0 Integrate.h struct Polynomial { "Polynomial.h" 25 lines Description: Simple integration of a function over an interval using Simp- int n; vector a; son’s rule. The error should be proportional to h4, although in practice you Polynomial(int n): n(n), a(n+1) {} void poly_roots(const Polynomial& p, double xmin, double xmax, vector& roots) { will want to verify that the result is stable to desired precision when epsilon double operator()(double x) const { changes. double val = 0; if (p.n == 1) { roots.push_back(-p.a.front()/p.a.back()); } 8 lines else { for(int i = n; i >= 0; --i) (val *= x) += a[i]; double quad(double (*f)(double), double a, double b) { return val; Polynomial d = p; const int n = 1000; } d.diff(); double h = (b - a) / 2 / n; void diff() { vector dr; double v = f(a) + f(b); poly_roots(d, xmin, xmax, dr); rep(i,1,n+1) a[i-1] = i*a[i]; rep(i,1,n*2) dr.push_back(xmin-1); a.pop_back(); --n; v += f(a + i*h) * (i&1 ? 4 : 2); dr.push_back(xmax+1); } return v * h / 3; void divroot(double x0) { sort(all(dr)); } double b = a.back(), c; a.back() = 0; for (auto i = dr.begin(), j = i++; i != dr.end(); j = i++){ double l = j, h = i, m, f; for(int i=n--; i--;) c = a[i], a[i] = a[i+1]*x0+b, b=c; * * a.pop_back(); bool sign = p(l) > 0; IntegrateAdaptive.h Description: Fast integration using an adaptive Simpson’s rule. } if (sign ˆ (p(h) > 0)) { Usage: double z, y; }; //for(int i = 0; i < 60; ++i ){ while(h - l > 1e-8) { double h(double x) { return x*x + y*y + z*z <= 1; } m = (l + h) / 2, f = p(m); double g(double y) { ::y = y; return quad(h, -1, 1); } BinarySearch.h if ((f <= 0) ˆ sign) l = m; double f(double z) { ::z = z; return quad(g, -1, 1); } Description: Finds a zero point of f on the interval [a b]. f(a) must be less double sphereVol = quad(f, -1, 1), pi = sphereVol 3/4; else h = m; * 16 lines than 0 and f(b) greater than 0. Useful for solving equations like kx=sin(x) } typedef double d; as in the example below. roots.push_back((l + h) / 2); d simpson(d ( f)(d), d a, d b) { Usage: double func(double x) { return .23*x-sin(x); } } * d c = (a+b) / 2; double x0 = bs(0,4,func); } return (f(a) + 4 f(c) + f(b)) (b-a) / 6; Time: O (log((b − a)/)) } * * 9 lines } } double bs(double a, double b, double (*f)(double)) { d rec(d (*f)(d), d a, d b, d eps, d S) { UiB Determinant IntDeterminant SolveLinear SolveLinear2 SolveLinearBinary 6

d c = (a+b) / 2; typedef double T; // long double, Rational, double + mod

... SolveLinear.h d S1 = simpson(f, a, c); typedef vector vd; Description: Solves A ∗ x = b. If there are multiple solutions, an arbitrary d S2 = simpson(f, c, b), T = S1 + S2; typedef vector vvd; one is returned. Returns rank, or -1 if no solutions. Data in A and b is lost. if (abs (T - S) <= 15 eps || b-a < 1e-10) Time: O n2m * 38 lines return T + (T - S) / 15; const T eps = 1e-8, inf = 1/.0; return rec(f, a, c, eps/2, S1) + rec(f, c, b, eps/2, S2); #define MP make_pair typedef vector vd; } #define ltj(X) if(s == -1 || MP(X[j],N[j]) < MP(X[s],N[s])) s=j const double eps = 1e-12; d quad(d (*f)(d), d a, d b, d eps = 1e-8) { return rec(f, a, b, eps, simpson(f, a, b)); struct LPSolver { int solveLinear(vector& A, vd& b, vd& x) { } int m, n; int n = sz(A), m = sz(x), rank = 0, br, bc; vi N, B; if (n) assert(sz(A[0]) == m); vvd D; vi col(m); iota(all(col), 0); Determinant.h Description: Calculates determinant of a matrix. Destroys the matrix. LPSolver(const vvd& A, const vd& b, const vd& c) : rep(i,0,n) { Time: O N 3 double v, bv = 0; 15 lines m(sz(b)), n(sz(c)), N(n+1), B(m), D(m+2, vd(n+2)) { rep(i,0,m) rep(j,0,n) D[i][j] = A[i][j]; rep(r,i,n) rep(c,i,m) double det(vector>& a) { if ((v = fabs(A[r][c])) > bv) int n = sz(a); double res = 1; rep(i,0,m) { B[i] = n+i; D[i][n] = -1; D[i][n+1] = b[i];} rep(j,0,n) { N[j] = j; D[m][j] = -c[j]; } br = r, bc = c, bv = v; rep(i,0,n) { if (bv <= eps) { int b = i; N[n] = -1; D[m+1][n] = 1; } rep(j,i,n) if (fabs(b[j]) > eps) return -1; rep(j,i+1,n) if (fabs(a[j][i]) > fabs(a[b][i])) b = j; break; if (i != b) swap(a[i], a[b]), res *= -1; void pivot(int r, int s) { } res *= a[i][i]; swap(A[i], A[br]); if (res == 0) return 0; T *a = D[r].data(), inv = 1 / a[s]; rep(i,0,m+2) if (i != r && abs(D[i][s]) > eps) { swap(b[i], b[br]); rep(j,i+1,n) { swap(col[i], col[bc]); T *b = D[i].data(), inv2 = b[s] * inv; double v = a[j][i] / a[i][i]; rep(j,0,n) swap(A[j][i], A[j][bc]); rep(j,0,n+2) b[j] -= a[j] * inv2; if (v != 0) rep(k,i+1,n) a[j][k] -= v * a[i][k]; bv = 1/A[i][i]; b[s] = a[s] * inv2; } rep(j,i+1,n) { } } double fac = A[j][i] * bv; return res; rep(j,0,n+2) if (j != s) D[r][j] *= inv; b[j] -= fac * b[i]; } rep(i,0,m+2) if (i != r) D[i][s] *= -inv; D[r][s] = inv; rep(k,i+1,m) A[j][k] -= fac*A[i][k]; swap(B[r], N[s]); } IntDeterminant.h } rank++; } Description: Calculates determinant using modular arithmetics. Modulos can also be removed to get a pure- version. bool simplex(int phase) { x.assign(m, 0); Time: O N 3 int x = m + phase - 1; 18 lines for (;;) { for (int i = rank; i--;) { const ll mod = 12345; int s = -1; b[i] /= A[i][i]; ll det(vector>& a) { rep(j,0,n+1) if (N[j] != -phase) ltj(D[x]); x[col[i]] = b[i]; int n = sz(a); ll ans = 1; if (D[x][s] >= -eps) return true; rep(j,0,i) b[j] -= A[j][i] * b[i]; rep(i,0,n) { int r = -1; } rep(j,i+1,n) { rep(i,0,m) { return rank; // (multiple solutions if rank < m) while (a[j][i] != 0) { // gcd step if (D[i][s] <= eps) continue; } ll t = a[i][i] / a[j][i]; if (r == -1 || MP(D[i][n+1] / D[i][s], B[i]) if (t) rep(k,i,n) < MP(D[r][n+1] / D[r][s], B[r])) r = i; a[i][k] = (a[i][k] - a[j][k] * t) % mod; } SolveLinear2.h swap(a[i], a[j]); if (r == -1) return false; Description: To get all uniquely determined values of x back from Solve- ans *= -1; pivot(r, s); Linear, make the following changes: } } "SolveLinear.h" 7 lines } } rep(j,0,n) if (j != i) // instead of rep(j,i+1,n) ans = ans * a[i][i] % mod; // ... then at the end: if (!ans) return 0; T solve(vd &x) { x.assign(m, undefined); } int r = 0; rep(i,0,rank) { return (ans + mod) % mod; rep(i,1,m) if (D[i][n+1] < D[r][n+1]) r = i; rep(j,rank,m) if (fabs(A[i][j]) > eps) goto fail; } if (D[r][n+1] < -eps) { x[col[i]] = b[i] / A[i][i]; pivot(r, n); fail:; } Simplex.h if (!simplex(2) || D[m+1][n+1] < -eps) return -inf; T rep(i,0,m) if (B[i] == -1) { Description: Solves a general linear maximization problem: maximize c x int s = 0; SolveLinearBinary.h subject to Ax ≤ b, x ≥ 0. Returns -inf if there is no solution, inf if there T rep(j,1,n+1) ltj(D[i]); Description: Solves Ax = b over F2. If there are multiple solutions, one is are arbitrarily good solutions, or the maximum value of c x otherwise. The pivot(i, s); returned arbitrarily. Returns rank, or -1 if no solutions. Destroys A and b. input vector is set to an optimal x (or in the unbounded case, an arbitrary Time: O n2m } 34 lines solution fulfilling the constraints). Numerical stability is not guaranteed. For } typedef bitset<1000> bs; better performance, define variables such that x = 0 is viable. bool ok = simplex(1); x = vd(n); vvd A = 1,-1 , -1,1 , -1,-2 ; Usage: {{ } { } { }} rep(i,0,m) if (B[i] < n) x[B[i]] = D[i][n+1]; vd b = 1,1,-4 , c = -1,-1 , x; int solveLinear(vector& A, vi& b, bs& x, int m) { { } { } return ok ? D[m][n+1] : inf; T val = LPSolver(A, b, c).solve(x); int n = sz(A), rank = 0, br; } assert(m <= sz(x)); Time: O (NM ∗ #pivots), where a pivot may be e.g. an edge relaxation. }; O (2n) in the general case. vi col(m); iota(all(col), 0); 68 lines rep(i,0,n) { UiB MatrixInverse Tridiagonal FFT ModularArithmetic ModInverse ModPow 7

for (br=i; br vd; Description: Solves a linear equation system with a tridiagonal ma- } vd conv(const vd& a, const vd& b) { trix with diagonal diag, subdiagonal sub and superdiagonal super, i.e., int bc = (int)A[br]._Find_next(i-1); int s = sz(a) + sz(b) - 1, L = 32-__builtin_clz(s), n = 1<

ModSum.h while (modpow(n, (p - 1) / 2, p) != p - 1) ++n; 5.3 Primality Description: Sums of mod’ed arithmetic progressions. ll x = modpow(a, (s + 1) / 2, p); Pto−1 modsum(to, c, k, m) = i=0 (ki + c)%m. divsum is similar but for ll b = modpow(a, s, p); floored division. ll g = modpow(n, s, p); eratosthenes.h Time: log(m), with a large constant. for (;;) { Description: Prime sieve for generating all primes up to a certain limit. 21 lines ll t = b; isprime[i] is true iff i is a prime. typedef unsigned long long ull; int m = 0; Time: lim=100’000’000 ≈ 0.8 s. Runs 30% faster if only odd indices are ull sumsq(ull to) { return to / 2 * ((to-1) | 1); } stored. for (; m < r; ++m) { 11 lines if (t == 1) break; ull divsum(ull to, ull c, ull k, ull m) { const int MAX_PR = 5000000; t = t * t % p; bitset isprime; ull res = k / m * sumsq(to) + c / m * to; } k %= m; c %= m; vi eratosthenes_sieve(int lim) { if (m == 0) return x; isprime.set(); isprime[0] = isprime[1] = 0; if (k) { ll gs = modpow(g, 1 << (r - m - 1), p); ull to2 = (to k + c) / m; for (int i = 4; i < lim; i += 2) isprime[i] = 0; * g = gs * gs % p; res += to to2; for (int i = 3; i*i < lim; i += 2) if (isprime[i]) * x = x * gs % p; res -= divsum(to2, m-1 - c, m, k) + to2; for (int j = i*i; j < lim; j += i*2) isprime[j] = 0; b = b * g % p; } vi pr; r = m; rep(i,2,lim) if (isprime[i]) pr.push_back(i); return res; } } return pr; } } ll modsum(ull to, ll c, ll k, ll m) { c %= m; k %= m; 5.2 Number theoretic transform MillerRabin.h if (c < 0) c += m; Description: Miller-Rabin primality probabilistic test. Probability of fail- if (k < 0) k += m; NTT.h ing one iteration is at most 1/4. 15 iterations should be enough for 50- . return to c + k sumsq(to) - m divsum(to, c, k, m); Description: Number theoretic transform. Can be used for convolutions * * * Time: 15 times the complexity of ab mod c. } modulo specific nice primes of the form 2ab + 1, where the convolution result "ModMulLL.h" has size at most 2a. For other primes/integers, use two different primes and 16 lines combine with CRT. May return negative values. bool prime(ull p) { ModMulLL.h Time: O (N log N) if (p == 2) return true; b Description: Calculate a · b mod c (or a mod c) for large c. "ModPow.h" 38 lines if (p == 1 || p % 2 == 0) return false; ull s = p - 1; Time: O (64/bits · log b), where bits = 64 − k, if we want to deal with k-bit const ll mod = (119 << 23) + 1, root = 3; // = 998244353 while (s % 2 == 0) s /= 2; numbers. // For p < 2ˆ30 there is also e.g. (5 << 25, 3) , (7 << 26, 3) , 19 lines rep(i,0,15) { // (479 << 21, 3) and (483 << 21, 5). The last two are > 10ˆ9. typedef unsigned long long ull; ull a = rand() % (p - 1) + 1, tmp = s; const int bits = 10; ull mod = mod_pow(a, tmp, p); typedef vector vl; // if all numbers are less than 2ˆk, set bits =64−k while (tmp != p - 1 && mod != 1 && mod != p - 1) { void ntt(ll x, ll temp, ll roots, int N, int skip) { const ull po = 1 << bits; * * * mod = mod_mul(mod, mod, p); if (N == 1) return; ull mod_mul(ull a, ull b, ull &c) { tmp = 2; int n2 = N/2; * ull x = a * (b & (po - 1)) % c; } ntt(x , temp, roots, n2, skip 2); while ((b >>= bits) > 0) { * if (mod != p - 1 && tmp % 2 == 0) return false; ntt(x+skip, temp, roots, n2, skip 2); a = (a << bits) % c; * } rep(i,0,N) temp[i] = x[i skip]; x += (a * (b & (po - 1))) % c; * return true; rep(i,0,n2) { } } return x % c; ll s = temp[2*i], t = temp[2*i+1] * roots[skip*i]; } x[skip*i] = (s + t) % mod; x[skip*(i+n2)] = (s - t) % mod; ull mod_pow(ull a, ull b, ull mod) { } factor.h if (b == 0) return 1; } Description: Pollard’s rho algorithm. It is a probabilistic factorisation ull res = mod_pow(a, b / 2, mod); void ntt(vl& x, bool inv = false){ algorithm, whose expected time complexity is good. Before you start using res = mod_mul(res, res, mod); ll e = modpow(root, (mod-1) / sz(x)); it, run init(bits), where bits is the length of the numbers you use. Returns if (b & 1) return mod_mul(res, a, mod); if (inv) e = modpow(e, mod-2); factors of the input without duplicates. return res; vl roots(sz(x), 1), temp = roots; Time: Expected running time should be good enough for 50-bit numbers. } rep(i,1,sz(x)) roots[i] = roots[i-1] * e % mod; "ModMulLL.h", "MillerRabin.h", "eratosthenes.h" 35 lines ntt(&x[0], &temp[0], &roots[0], sz(x), 1); vector pr; } ull f(ull a, ull n, ull &has) { vl conv(vl a, vl b) { ModSqrt.h return (mod_mul(a, a, n) + has) % n; int s = sz(a) + sz(b) - 1; if (s <= 0) return {}; Description: Tonelli-Shanks algorithm for modular square roots. } 2  int L = s > 1 ? 32 - __builtin_clz(s - 1) : 0, n = 1 << L; Time: O log p worst case, often O (log p) vector factor(ull d) { if (s <= 200) { // (factor 10 optimization for |a | , | b | = 10) "ModPow.h" 30 lines vector res; vl c(s); ll sqrt(ll a, ll p) { for (int i = 0; i < sz(pr) && pr[i] pr[i] <= d; i++) rep(i,0,sz(a)) rep(j,0,sz(b)) * a %= p; if (a < 0) a += p; if (d % pr[i] == 0) { c[i + j] = (c[i + j] + a[i] b[j]) % mod; if (a == 0) return 0; * while (d % pr[i] == 0) d /= pr[i]; return c; assert(modpow(a, (p-1)/2, p) == 1); res.push_back(pr[i]); } if (p % 4 == 3) return modpow(a, (p+1)/4, p); } a.resize(n); ntt(a); // aˆ(n+3)/8 or 2ˆ(n+3)/8 ∗ 2ˆ(n−1)/4 works if p % 8 == 5 b.resize(n); ntt(b); //d is now a product of at most 2 primes. ll s = p - 1; if (d > 1) { vl c(n); ll d = modpow(n, mod-2); int r = 0; if (prime(d)) rep(i,0,n) c[i] = a[i] b[i] % mod d % mod; while (s % 2 == 0) * * res.push_back(d); ntt(c, true); c.resize(s); return c; ++r, s /= 2; else while (true){ } ll n = 2; // find a non−square mod p ull has = rand() % 2321 + 47; UiB euclid Euclid phiFunction chinese intperm 9

ull x = 2, y = 2, c = 1; phiFunction.h Primitive roots exist modulo any pa, except for for (; c==1; c = __gcd((y > x ? y - x : x - y), d)) { Description: Euler’s totient or Euler’s phi function is defined as φ(n) := a x = f(x, d, has); # of positive integers ≤ n that are coprime with n. The cototient is n−φ(n). p = 2, a > 2, and there are φ(φ(p )) many. For p = 2, a > 2, k k−1 × y = f(f(y, d, has), d, has); φ(1) = 1, p prime ⇒ φ(p ) = (p − 1)p , m, n coprime ⇒ φ(mn) = the group Z2a is instead isomorphic to Z2 × Z2a−2 . } k1 k2 kr k1−1 kr −1 φ(m)φ(n). If n = p p ...p then φ(n) = (p1 − 1)p ...(pr − 1)p . if (c != d) { Q 1 2 r 1 r φ(n) = n · p|n(1 − 1/p). res.push_back(c); d /= c; P P 5.8 Estimates if (d != c) res.push_back(d); d|n φ(d) = n, 1≤k≤n,gcd(k,n)=1 k = nφ(n)/2, n > 1 break; Euler’s thm: a, n coprime ⇒ aφ(n) ≡ 1 (mod n). P d = O(n log log n). } Fermat’s little thm: p prime ⇒ ap−1 ≡ 1 (mod p) ∀a. d|n } 10 lines } const int LIM = 5000000; The number of of n is at most around 100 for return res; int phi[LIM]; n < 5e4, 500 for n < 1e7, 2000 for n < 1e10, 200 000 for } void init(int bits) {//how many bits do we use? void calculatePhi() { n < 1e19. vi p = eratosthenes_sieve(1 << ((bits + 2) / 3)); rep(i,0,LIM) phi[i] = i&1 ? i : i/2; pr.assign(all(p)); for(int i = 3; i < LIM; i += 2) } if(phi[i] == i) Combinatorial (6) for(int j = i; j < LIM; j += i) (phi[j] /= i) *= i-1; } 6.1 The Twelvefold Way 5.4 Divisibility Counts the # of functions f : N → K, |N| = n, |K| = k. 5.5 Chinese remainder theorem The elements in N and K can be distinguishable or euclid.h indistinguishable, while f can be injective (one-to-one) of Description: Finds the Greatest Common to the integers a and b. Euclid also finds two integers x and y, such that ax + by = gcd(a, b). If a chinese.h surjective (onto). and b are coprime, then x is the inverse of a (mod b). Description: Chinese Remainder Theorem. 7 lines chinese(a, m, b, n) returns a number x, such that x ≡ a (mod m) and NK none injective surjective ll gcd(ll a, ll b) { return __gcd(a, b); } x ≡ b (mod n). For not coprime n, m, use chinese common. Note that all numbers must be less than 231 if you have Z = unsigned long long. dist dist kn k! k!S(n, k) ll euclid(ll a, ll b, ll &x, ll &y) { (k−n)! Time: log(m + n) n+k−1 k n−1 if (b) { ll d = euclid(b, a % b, y, x);    "euclid.h" 13 lines indist dist n n n−k return y -= a/b x, d; } * template Z chinese(Z a, Z m, Z b, Z n) { dist indist Pk S(n, t)[n ≤ k] S(n, k) return x = 1, y = 0, a; Z x, y; euclid(m, n, x, y); t=0 k } Z ret = a (y + m) % m n + b (x + n) % n m; P * * * * indist indist t=1 p(n, t)[n ≤ k] p(n, k) if (ret >= m * n) ret -= m * n; return ret; Here, S(n, k) is the Stirling number of the second kind, and Euclid.java } Description: Finds {x, y, d} s.t. ax + by = d = gcd(a, b). 11 lines p(n, k) is the partition number. static BigInteger[] euclid(BigInteger a, BigInteger b) { template Z chinese_common(Z a, Z m, Z b, Z n) { BigInteger x = BigInteger.ONE, yy = x; Z d = gcd(m, n); BigInteger y = BigInteger.ZERO, xx = y; if (((b -= a) %= n) < 0) b += n; 6.2 Permutations while (b.signum() != 0) { if (b % d) return -1; // No solution BigInteger q = a.divide(b), t = b; return d * chinese(Z(0), m/d, b/d, n/d) + a; 6.2.1 b = a.mod(b); a = t; } t = xx; xx = x.subtract(q.multiply(xx)); x = t; n 1 2 3 4 5 6 7 8 9 10 t = yy; yy = y.subtract(q.multiply(yy)); y = t; } 5.6 Pythagorean Triples n! 1 2 6 24 120 720 5040 40320 362880 3628800 return new BigInteger[]{x, y, a}; n 11 12 13 14 15 16 17 } The Pythagorean triples are uniquely generated by n! 4.0e7 4.8e8 6.2e9 8.7e10 1.3e12 2.1e13 3.6e14 5.4.1 B´ezout’sidentity n 20 25 30 40 50 100 150 171 a = k · (m2 − n2), b = k · (2mn), c = k · (m2 + n2), n! 2e18 2e25 3e32 8e47 3e64 9e157 6e262 >DBL MAX For a 6=, b 6= 0, then d = gcd(a, b) is the smallest positive intperm.h integer for which there are integer solutions to with m > n > 0, k > 0, m⊥n, and either m or n even. Description: to/from integers. The bijection is order pre- serving. Time: O n2 ax + by = d 20 lines 5.7 Primes int factorial[] = {1, 1, 2, 6, 24, 120, 720, 5040}; // etc . template 21 void perm_to_int(Z& val, It begin, It end) { If (x, y) is one solution, then all solutions are given by p = 962592769 is such that 2 | p − 1, which may be useful. int x = 0, n = 0; For hashing use 970592641 (31-bit number), 31443539979727 for (It i = begin; i != end; ++i, ++n)  kb ka  (45-bit), 3006703054056749 (52-bit). There are 78498 primes if (*i < *begin) ++x; x + , y − , k ∈ if (n > 2) perm_to_int(val, ++begin, end); gcd(a, b) gcd(a, b) Z less than 1 000 000. else val = 0; UiB derangements 10

val += factorial[n-1]*x; if (vals[j] > i) p = DGen(m-1, k-1); 6.2.7 Burnside’s lemma } else if (vals[j] < i) p = DGen(m-1, k); /∗ range [begin, end) does not have to be sorted. ∗/ if (idx <= p) break; Given a group G of symmetries and a set X, the number of template idx -= p; void int_to_perm(Z val, It begin, It end) { } elements of X up to symmetry equals Z fac = factorial[end - begin - 1]; res[i] = vals[j]; // Note that the division result will fit in an integer! memmove(vals + j, vals + j + 1, sizeof(int)*(m-j-1)); 1 X int x = val / fac; } |Xg|, nth_element(begin, begin + x, end); } |G| g∈G swap(*begin, *(begin + x)); }; if (end - begin > 2) int_to_perm(val % fac, ++begin, end); } where Xg are the elements fixed by g (g.x = x). 6.2.4 Involutions If f(n) counts ”configurations” (of some sort) of length n, we 6.2.2 Cycles An involution is a with maximum cycle length can ignore rotational symmetry using G = Zn to get Let the number of n-permutations whose cycle lengths all 2, and it is its own inverse. n−1 belong to the set S be denoted by gS(n). Then 1 X 1 X a(n) = a(n − 1) + (n − 1)a(n − 2) g(n) = f(gcd(n, k)) = f(k)φ(n/k). ∞ ! n n X xn X xn k=0 k|n g (n) = exp a(0) = a(1) = 1 S n! n n=0 n∈S 1, 1, 2, 4, 10, 26, 76, 232, 764, 2620, 9496, 35696, 6.3 Partitions and subsets 140152 6.2.3 Derangements 6.3.1 Partition function 6.2.5 Stirling numbers of the first kind Permutations of a set such that none of the elements appear Partitions of n with exactly k parts, p(n, k), i.e., writing n in their original position. as a sum of k positive integers, disregarding the order of the s(n, k) = (−1)n−kc(n, k) summands. n! D(n) = (n−1)(D(n−1)+D(n−2)) = nD(n−1)+(−1)n = e c(n, k) is the unsigned Stirling numbers of the first kind, and p(n, k) = p(n − 1, k − 1) + p(n − k, k) they count the number of permutations on n items with k derangements.h cycles. p(0, 0) = p(1, n) = p(n, n) = p(n, n − 1) = 1 Description: Generates the i:th derangement of Sn (in lexicographical order). 38 lines s(n, k) = s(n − 1, k − 1) − (n − 1)s(n − 1, k) For partitions with any number of parts, p(n) obeys template struct derangements { X k+1 T dgen[N][N], choose[N][N], fac[N]; s(0, 0) = 1, s(n, 0) = s(0, n) = 0 p(0) = 1, p(n) = (−1) p(n − k(3k − 1)/2) derangements() { k∈ \{0} fac[0] = choose[0][0] = 1; c(n, k) = c(n − 1, k − 1) + (n − 1)c(n − 1, k) Z memset(dgen, 0, sizeof(dgen)); √ rep(m,1,N) { c(0, 0) = 1, c(n, 0) = c(0, n) = 0 p(n) ∼ 0.145/n · exp(2.56 n) fac[m] = fac[m-1] * m; choose[m][0] = choose[m][m] = 1; n 0 1 2 3 4 5 6 7 8 9 20 50 100 rep(k,1,m) choose[m][k] = choose[m-1][k-1] + choose[m-1][k]; 6.2.6 Eulerian numbers p(n) 1 1 2 3 5 7 11 15 22 30 627 ∼2e5 ∼2e8 } } Number of permutations π ∈ Sn in which exactly k elements T DGen(int n, int k) { T ans = 0; are greater than the previous element. k j:s s.t. if (dgen[n][k]) return dgen[n][k]; π(j) > π(j + 1), k + 1 j:s s.t. π(j) ≥ j, k j:s s.t. rep(i,0,k+1) π(j) > j. ans += (i&1?-1:1) * choose[k][i] * fac[n-i]; return dgen[n][k] = ans; } E(n, k) = (n − k)E(n − 1, k − 1) + (k + 1)E(n − 1, k) void generate(int n, T idx, int *res) { int vals[N]; rep(i,0,n) vals[i] = i; E(n, 0) = E(n, n − 1) = 1 rep(i,0,n) { int j, k = 0, m = n - i; k   rep(j,0,m) if (vals[j] > i) ++k; X j n + 1 n rep(j,0,m) { E(n, k) = (−1) (k + 1 − j) j T p = 0; j=0 UiB binomial binomialModPrime RollingBinomial multinomial 11 6.3.2 Binomials 6.3.3 Stirling numbers of the second kind • # of monotonic lattice paths of a n × n-grid which do not pass above the diagonal. Partitions of n distinct elements into exactly k binomial.h groups. • # of expressions containing n pairs of parenthesis Description: The number of k-element subsets of an n-element set, which are correctly matched. n = n! k k!(n−k)! S(n, k) = S(n − 1, k − 1) + kS(n − 1, k) Time: O (min(k, n − k)) 6 lines • # of full binary trees with with n + 1 leaves (0 or 2 ll choose(int n, int k) { S(n, 1) = S(n, n) = 1 children). ll c = 1, to = min(k, n-k); if (to < 0) return 0; k   • # of non-isomorphic ordered trees with n + 1 vertices. rep(i,0,to) c = c (n - i) / (i + 1); 1 X k * S(n, k) = (−1)k−j jn return c; k! j • # of ways a convex polygon with n + 2 sides can be } j=0 cut into triangles by connecting vertices with straight 6.3.4 Bell numbers lines. binomialModPrime.h Description: Lucas’ thm: Let n, m be non-negative integers and p a prime. Total number of partitions of n distinct elements. • # of permutations of [n] with no three-term increasing k k Write n = nkp + ... + n1p + n0 and m = mkp + ... + m1p + m0. Then subsequence. n  ≡ Qk ni  (mod p). fact and invfact must hold pre-computed facto- n n m i=0 mi n − 1 rials / inverse , e.g. from ModInverse.h. X X  B(n) = B(n − k) = S(n, k) 6.4.2 Super Catalan numbers Time: O logp n k − 1 10 lines k=1 k=1 ll chooseModP(ll n, ll m, int p, vi& fact, vi& invfact) { The number of monotonic lattice paths of a n × n-grid that ll c = 1; while (n || m) { B(0) = B(1) = 1 do not touch the diagonal. ll a = n % p, b = m % p; The first are 1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, if (a < b) return 0; 3(2n − 3)S(n − 1) − (n − 3)S(n − 2) c = c * fact[a] % p * invfact[b] % p * invfact[a - b] % p; 678570, 4213597. For a prime p S(n) = n /= p; m /= p; n } m return c; B(p + n) ≡ mB(n) + B(n + 1) (mod p) S(1) = S(2) = 1 } 1, 1, 3, 11, 45, 197, 903, 4279, 20793, 103049, 518859 6.3.5 Triangles RollingBinomial.h 6.4.3 Motzkin numbers n Given rods of length 1, . . . , n, Description: k (mod m) in time proportional to the difference between (n, k) and the previous (n, k). 14 lines 1  n(n − 2)(2n − 5) n even Number of ways of drawing any number of nonintersecting const ll mod = 1000000007; T (n) = chords among n points on a circle. Number of lattice paths vector invs; // precomputed up to max n, inclusively 24 (n − 1)(n − 3)(2n − 1) n odd struct Bin { from (0, 0) to (n, 0) never going below the x-axis, using only int N = 0, K = 0; ll r = 1; is the number of distinct triangles (positive are) that can be steps NE, E, SE. void m(ll a, ll b) { r = r * a % mod * invs[b] % mod; } ll choose(int n, int k) { constructed, i.e., the # of 3-subsets of [n] s.t. x ≤ y ≤ z and 3(n − 1)M(n − 2) + (2n + 1)M(n − 1) if (k > n || k < 0) return 0; z 6= x + y. M(n) = while (N < n) ++N, m(N, N-K); n + 2 while (K < k) ++K, m(N-K+1, K); while (K > k) m(K, N-K+1), --K; 6.4 General purpose numbers while (N > n) m(N-K, N), --N; M(0) = M(1) = 1 return r; } 6.4.1 Catalan numbers 1, 1, 2, 4, 9, 21, 51, 127, 323, 835, 2188, 5798, 15511, 41835, }; 113634 1 2n 2n  2n  (2n)! C = = − = n n + 1 n n n + 1 (n + 1)!n! 6.4.4 Narayana numbers multinomial.h P P Description: ki  = ( ki)! k ,k ,...,kn k !k !...kn! Number of lattice paths from (0, 0) to (2n, 0) never going P 1 2 1 2 2(2n + 1) Time: O (( ki) − k1) C = C 6 lines n+1 n + 2 n below the x-axis, using only steps NE and SE, and with k ll multinomial(vi& v) { peaks. ll c = 1, m = v.empty() ? 1 : v[0]; X C0 = 1,Cn+1 = CiCn−i 1 n n  rep(i,1,sz(v)) rep(j,0,v[i]) N(n, k) = c = c * ++m / (j+1); n k k − 1 return c; First few are 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, } 58786, 208012, 742900. N(n, 1) = N(n, n) = 1 UiB bellmanFord FloydWarshall TopoSort EulerWalk PushRelabel 12 n X int n = sz(m); // else , non−cycle if ret.front() != ret.back() N(n, k) = Cn rep(i,0,n) m[i][i] = min(m[i][i], {}); reverse(all(ret)); k=1 rep(k,0,n) rep(i,0,n) rep(j,0,n) return ret; if (m[i][k] != inf && m[k][j] != inf) { } 1, 1, 1, 1, 3, 1, 1, 6, 6, 1, 1, 10, 20, 10, 1, 1, 15, 50 auto newDist = max(m[i][k] + m[k][j], -inf); m[i][j] = min(m[i][j], newDist); } 7.3 Network flow 6.4.5 Schr¨odernumbers rep(k,0,n) if (m[k][k] < 0) rep(i,0,n) rep(j,0,n) if (m[i][k] != inf && m[k][j] != inf) m[i][j] = -inf; } PushRelabel.h Number of lattice paths from (0, 0) to (n, n) using only steps Description: Push-relabel using the highest label selection rule and the N,NE,E, never going above the diagonal. Number of lattice gap heuristic. Quite fast in practice. To obtain the actual flow, look at TopoSort.h positive values only. paths from (0, 0) to (2n, 0) using only steps NE, SE and  √  Description: Topological sorting. Given is an oriented graph. Output is Time: O V 2 E double east EE, never going below the x-axis. Twice the an ordering of vertices (array idx), such that there are edges only from left 51 lines to right. The function returns false if there is a cycle in the graph. typedef ll Flow; Super , except for the first term. 1, 2, 6, 22, Time: O (|V | + |E|) struct Edge { 18 lines 90, 394, 1806, 8558, 41586, 206098 int dest, back; template Flow f, c; bool topo_sort(const E &edges, I &idx, int n) { }; Graph (7) vi indeg(n); rep(i,0,n) struct PushRelabel { trav(e, edges[i]) vector> g; 7.1 Fundamentals indeg[e]++; vector ec; queue q; // use priority queue for lexic. smallest ans. vector cur; rep(i,0,n) if (indeg[i] == 0) q.push(-i); vector hs; vi H; bellmanFord.h int nr = 0; PushRelabel(int n) : g(n), ec(n), cur(n), hs(2*n), H(n) {} Description: Calculates shortest path in a graph that might have negative while (q.size() > 0) { edge distances. Propagates negative infinity distances (sets dist = -inf), and int i = -q.front(); // top() for priority queue returns true if there is some negative cycle. Unreachable nodes get dist = void add_edge(int s, int t, Flow cap, Flow rcap=0) { idx[i] = nr++; if (s == t) return; inf. q.pop(); Time: O (EV ) Edge a = {t, sz(g[t]), 0, cap}; 27 lines trav(e, edges[i]) Edge b = {s, sz(g[s]), 0, rcap}; typedef ll T; // or whatever if (--indeg[e] == 0) q.push(-e); g[s].push_back(a); struct Edge { int src, dest; T weight; }; } g[t].push_back(b); struct Node { T dist; int prev; }; return nr == n; } struct Graph { vector nodes; vector edges; }; } void add_flow(Edge& e, Flow f) { const T inf = numeric_limits::max(); Edge &back = g[e.dest][e.back]; bool bellmanFord2(Graph& g, int start_node) { 7.2 Euler walk if (!ec[e.dest] && f) hs[H[e.dest]].push_back(e.dest); trav(n, g.nodes) { n.dist = inf; n.prev = -1; } e.f += f; e.c -= f; ec[e.dest] += f; g.nodes[start_node].dist = 0; EulerWalk.h back.f -= f; back.c += f; ec[back.dest] -= f; Description: Eulerian undirected/directed path/cycle algorithm. Returns } rep(i,0,sz(g.nodes)) trav(e, g.edges) { a list of nodes in the Eulerian path/cycle with src at both start and end, Flow maxflow(int s, int t) { Node& cur = g.nodes[e.src]; or empty list if no cycle/path exists. To get edge indices back, also put int v = sz(g); H[s] = v; ec[t] = 1; Node& dest = g.nodes[e.dest]; it->second in s (and then ret). vi co(2*v); co[0] = v-1; if (cur.dist == inf) continue; Time: O (E) where E is the number of edges. rep(i,0,v) cur[i] = g[i].data(); T ndist = cur.dist + (cur.dist == -inf ? 0 : e.weight); 27 lines trav(e, g[s]) add_flow(e, e.c); if (ndist < dest.dist) { struct V{ dest.prev = e.src; vector outs; // (dest, edge index) for (int hi = 0;;) { dest.dist = (i >= sz(g.nodes)-1 ? -inf : ndist); int nins = 0; while (hs[hi].empty()) if (!hi--) return -ec[s]; } }; int u = hs[hi].back(); hs[hi].pop_back(); } while (ec[u] > 0) // discharge u bool ret = 0; vi euler_walk(vector& nodes, int nedges, int src=0) { if (cur[u] == g[u].data() + sz(g[u])) { rep(i,0,sz(g.nodes)) trav(e, g.edges) { int c = 0; H[u] = 1e9; if (g.nodes[e.src].dist == -inf) trav(n, nodes) c += abs(n.nins - sz(n.outs)); trav(e, g[u]) if (e.c && H[u] > H[e.dest]+1) g.nodes[e.dest].dist = -inf, ret = 1; if (c > 2) return {}; H[u] = H[e.dest]+1, cur[u] = &e; } vector::iterator> its; if (++co[H[u]], !--co[hi] && hi < v) return ret; trav(n, nodes) rep(i,0,v) if (hi < H[i] && H[i] < v) } its.push_back(n.outs.begin()); --co[H[i]], H[i] = v + 1; vector eu(nedges); hi = H[u]; FloydWarshall.h vi ret, s = {src}; } else if (cur[u]->c && H[u] == H[cur[u]->dest]+1) Description: Calculates all-pairs shortest path in a directed graph that while(!s.empty()) { add_flow(*cur[u], min(ec[u], cur[u]->c)); might have negative edge distances. Input is an distance matrix m, where int x = s.back(); else ++cur[u]; m[i][j] = inf if i and j are not adjacent. As output, m[i][j] is set to the auto& it = its[x], end = nodes[x].outs.end(); } shortest distance between i and j, inf if no path, or -inf if the path goes while(it != end && eu[it->second]) ++it; } through a negative-weight cycle. if(it == end) { ret.push_back(x); s.pop_back(); } }; Time: O N 3 else { s.push_back(it->first); eu[it->second] = true;} 12 lines } const ll inf = 1LL << 62; if(sz(ret) != nedges+1) void floydWarshall(vector>& m) { ret.clear(); // No Eulerian cycles/paths. UiB MinCostMaxFlow EdmondsKarp MinCut GlobalMinCut hopcroftKarp 13

MinCostMaxFlow.h if (r) flow[p][x] += fl; GlobalMinCut.h Description: Min-cost max-flow. cap[i][j] != cap[j][i] is allowed; double else flow[x][p] -= fl; Description: Find a global minimum cut in an undirected graph, as rep- edges are not. If costs can be negative, call setpi before maxflow, but note } resented by an adjacency matrix. that negative cost cycles are not allowed (that’s NP-hard). To obtain the rep(i,0,N) rep(j,0,N) totcost += cost[i][j] flow[i][j]; Time: O V 3 * 31 lines actual flow, look at positive values only. return {totflow, totcost}; Time: Approximately O E2 } pair GetMinCut(vector& weights) { 81 lines int N = sz(weights); #include // If some costs can be negative, call this before maxflow: vi used(N), cut, best_cut; void setpi(int s) { // (otherwise, leave this out) int best_weight = -1; const ll INF = numeric_limits::max() / 4; fill(all(pi), INF); pi[s] = 0; typedef vector VL; int it = N, ch = 1; ll v; for (int phase = N-1; phase >= 0; phase--) { while (ch-- && it--) vi w = weights[0], added = used; struct MCMF { rep(i,0,N) if (pi[i] != INF) int prev, k = 0; int N; trav(to, ed[i]) if (cap[i][to]) rep(i,0,phase){ vector ed, red; if ((v = pi[i] + cost[i][to]) < pi[to]) prev = k; vector cap, flow, cost; pi[to] = v, ch = 1; k = -1; vi seen; assert(it >= 0); // negative cost cycle rep(j,1,N) VL dist, pi; } if (!added[j] && (k == -1 || w[j] > w[k])) k = j; vector par; }; if (i == phase-1) { rep(j,0,N) weights[prev][j] += weights[k][j]; MCMF(int N) : rep(j,0,N) weights[j][prev] = weights[prev][j]; N(N), ed(N), red(N), cap(N, VL(N)), flow(cap), cost(cap), used[k] = true; seen(N), dist(N), pi(N), par(N) {} EdmondsKarp.h cut.push_back(k); 2 Description: Flow algorithm with guaranteed complexity O(VE ). To get if (best_weight == -1 || w[k] < best_weight) { void addEdge(int from, int to, ll cap, ll cost) { edge flow values, compare capacities before and after, and take the positive best_cut = cut; values only. this->cap[from][to] = cap; 35 lines best_weight = w[k]; this->cost[from][to] = cost; template T edmondsKarp(vector>& } ed[from].push_back(to); graph, int source, int sink) { } else { red[to].push_back(from); assert(source != sink); rep(j,0,N) } T flow = 0; w[j] += weights[k][j]; vi par(sz(graph)), q = par; added[k] = true; void path(int s) { } fill(all(seen), 0); for (;;) { } fill(all(dist), INF); fill(all(par), -1); } dist[s] = 0; ll di; par[source] = 0; return {best_weight, best_cut}; int ptr = 1; } __gnu_pbds::priority_queue> q; q[0] = source; vector its(N); q.push({0, s}); rep(i,0,ptr) { 7.4 Matching int x = q[i]; auto relax = [&](int i, ll cap, ll cost, int dir) { trav(e, graph[x]) { ll val = di - pi[i] + cost; hopcroftKarp.h if (par[e.first] == -1 && e.second > 0) { Description: Find a maximum matching in a bipartite graph. if (cap && val < dist[i]) { par[e.first] = x; dist[i] = val; Usage: vi ba(m, -1); hopcroftKarp(g, ba); q[ptr++] = e.first; √  par[i] = {s, dir}; if (e.first == sink) goto out; Time: O VE if (its[i] == q.end()) its[i] = q.push({-dist[i], i}); 48 lines } bool dfs(int a, int layer, const vector& g, vi& btoa, else q.modify(its[i], {-dist[i], i}); } } vi& A, vi& B) { } if (A[a] != layer) return 0; }; return flow; A[a] = -1; out: while (!q.empty()) { trav(b, g[a]) if (B[b] == layer + 1) { T inc = numeric_limits::max(); B[b] = -1; s = q.top().second; q.pop(); for int ( y = sink; y != source; y = par[y]) if (btoa[b] == -1 || dfs(btoa[b], layer+2, g, btoa, A, B)) seen[s] = 1; di = dist[s] + pi[s]; inc = min(inc, graph[par[y]][y]); trav(i, ed[s]) if (!seen[i]) return btoa[b] = a, 1; relax(i, cap[s][i] - flow[s][i], cost[s][i], 1); } flow += inc; return 0; trav(i, red[s]) if (!seen[i]) for int ( y = sink; y != source; y = par[y]) { } relax(i, flow[i][s], -cost[i][s], 0); int p = par[y]; } if ((graph[p][y] -= inc) <= 0) graph[p].erase(y); int hopcroftKarp(const vector& g, vi& btoa) { rep(i,0,N) pi[i] = min(pi[i] + dist[i], INF); graph[y][p] += inc; } int res = 0; } vi A(g.size()), B(btoa.size()), cur, next; } for (;;) { pair maxflow(int s, int t) { } ll totflow = 0, totcost = 0; fill(all(A), 0); while (path(s), seen[t]) { fill(all(B), -1); ll fl = INF; for (int p,r,x = t; tie(p,r) = par[x], x != s; x = p) MinCut.h cur.clear(); fl = min(fl, r ? cap[p][x] - flow[p][x] : flow[x][p]); Description: After running max-flow, the left side of a min-cut from s to t trav(a, btoa) if(a != -1) A[a] = -1; totflow += fl; is given by all vertices reachable from s, only traversing edges with positive rep(a,0,sz(g)) if(A[a] == 0) cur.push_back(a); residual capacity. for (int p,r,x = t; tie(p,r) = par[x], x != s; x = p) 1 lines for (int lay = 1;; lay += 2) { UiB DFSMatching WeightedMatching GeneralMatching MinimumVertexCover 14

bool islast = 0; GeneralMatching.h next.clear(); rep(i,0,n) { Description: Matching for general graphs. Fails with probability N/mod. trav(a, cur) trav(b, g[a]) { u[i] = cost[i][0]; Time: O N 3 if (btoa[b] == -1) { rep(j,1,n) u[i] = min(u[i], cost[i][j]); "../numerical/MatrixInverse-mod.h" 40 lines B[b] = lay; } vector generalMatching(int N, vector& ed) { islast = 1; rep(j,0,n) { vector> mat(N, vector(N)), A; } v[j] = cost[0][j] - u[0]; trav(pa, ed) { else if (btoa[b] != a && B[b] == -1) { rep(i,1,n) v[j] = min(v[j], cost[i][j] - u[i]); int a = pa.first, b = pa.second, r = rand() % mod; B[b] = lay; } mat[a][b] = r, mat[b][a] = (mod - r) % mod; next.push_back(btoa[b]); } } L = R = vi(n, -1); } rep(i,0,n) rep(j,0,n) { int r = matInv(A = mat), M = 2*N - r, fi, fj; if (islast) break; if (R[j] != -1) continue; assert(r % 2 == 0); if (next.empty()) return res; if (zero(cost[i][j] - u[i] - v[j])) { trav(a, next) A[a] = lay+1; L[i] = j; if (M != N) do { cur.swap(next); R[j] = i; mat.resize(M, vector(M)); } mated++; rep(i,0,N) { break; mat[i].resize(M); rep(a,0,sz(g)) { } rep(j,N,M) { if(dfs(a, 0, g, btoa, A, B)) } int r = rand() % mod; ++res; mat[i][j] = r, mat[j][i] = (mod - r) % mod; } for (; mated < n; mated++) { // until solution is feasible } } int s = 0; } } while (L[s] != -1) s++; } while (matInv(A = mat) != M); fill(all(dad), -1); DFSMatching.h fill(all(seen), 0); vi has(M, 1); vector ret; rep(k,0,n) rep(it,0,M/2) { Description: This is a simple matching algorithm but should be just fine dist[k] = cost[s][k] - u[s] - v[k]; in most cases. Graph g should be a list of neighbours of the left partition. rep(i,0,M) if (has[i]) n is the size of the left partition and m is the size of the right partition. If rep(j,i+1,M) if (A[i][j] && mat[i][j]) { int j = 0; fi = i; fj = j; goto done; you want to get the matched pairs, match[i] contains match for vertex i on for (;;) { the right side or −1 if it’s not matched. } assert(0); done: j = -1; if (fj < N) ret.emplace_back(fi, fj); Time: O (EV ) where E is the number of edges and V is the number of rep(k,0,n){ vertices. has[fi] = has[fj] = 0; 24 lines if (seen[k]) continue; rep(sw,0,2) { vi match; if (j == -1 || dist[k] < dist[j]) j = k; ll a = modpow(A[fi][fj], mod-2); vector seen; } rep(i,0,M) if (has[i] && A[i][fj]) { bool find(int j, const vector& g) { seen[j] = 1; ll b = A[i][fj] * a % mod; if (match[j] == -1) return 1; int i = R[j]; rep(j,0,M) A[i][j] = (A[i][j] - A[fi][j] * b) % mod; seen[j] = 1; int di = match[j]; if (i == -1) break; } trav(e, g[di]) rep(k,0,n) { swap(fi,fj); if (!seen[e] && find(e, g)) { if (seen[k]) continue; } match[e] = di; auto new_dist = dist[j] + cost[i][k] - u[i] - v[k]; } return 1; if (dist[k] > new_dist) { return ret; } dist[k] = new_dist; } return 0; dad[k] = j; } } int dfs_matching(const vector& g, int n, int m) { } 7.5 Minimum vertex cover match.assign(m, -1); } rep(i,0,n) { seen.assign(m, 0); rep(k,0,n) { MinimumVertexCover.h trav(j,g[i]) if (k == j || !seen[k]) continue; Description: Finds a minimum vertex cover in a bipartite graph. The size if (find(j, g)) { auto w = dist[k] - dist[j]; is the same as the size of a maximum matching, and the complement is an match[j] = i; v[k] += w, u[R[k]] -= w; independent set. break; } "DFSMatching.h" 20 lines u[s] += dist[j]; } vi cover(vector& g, int n, int m) { } int res = dfs_matching(g, n, m); while (dad[j] >= 0) { return m - (int)count(all(match), -1); seen.assign(m, false); int d = dad[j]; } vector lfound(n, true); R[j] = R[d]; trav(it, match) if (it != -1) lfound[it] = false; L[R[j]] = j; vi q, cover; WeightedMatching.h j = d; rep(i,0,n) if (lfound[i]) q.push_back(i); Description: Min cost bipartite matching. Negate costs for max cost. } 3 while (!q.empty()) { Time: O N R[j] = s; 79 lines int i = q.back(); q.pop_back(); L[s] = j; typedef vector vd; lfound[i] = 1; } bool zero(double x) { return fabs(x) < 1e-10; } trav(e, g[i]) if (!seen[e] && match[e] != -1) { auto value = vd(1)[0]; double MinCostMatching(const vector& cost, vi& L, vi& R) { seen[e] = true; rep(i,0,n) value += cost[i][L[i]]; int n = sz(cost), mated = 0; q.push_back(match[e]); return value; vd dist(n), u(n), v(n); } } vi dad(n), seen(n); } UiB SCC BiconnectedComponents 2sat TreePower LCA 15

rep(i,0,n) if (!lfound[i]) cover.push_back(i); } else { } rep(i,0,m) if (seen[i]) cover.push_back(n+i); int si = sz(st); assert(sz(cover) == res); int up = dfs(y, e, f); vi val, comp, z; int time = 0; return cover; top = min(top, up); int dfs(int i) { } if (up == me) { int low = val[i] = ++time, x; z.push_back(i); st.push_back(e); trav(e, gr[i]) if (!comp[e]) f(vi(st.begin() + si, st.end())); low = min(low, val[e] ?: dfs(e)); 7.6 DFS algorithms st.resize(si); ++time; } if (low == val[i]) do { else if (up < me) x = z.back(); z.pop_back(); SCC.h st.push_back(e); comp[x] = time; Description: Finds strongly connected components in a directed graph. If // else e is a bridge if (values[x>>1] == -1) vertices u, v belong to the same component, we can reach u from v and vice } values[x>>1] = !(x&1); versa. } } while (x != i); Usage: scc(graph, [&](vi& v) { ... }) visits all components return top; return val[i] = low; in reverse topological order. comp[i] holds the component } } index of a node (a component only has edges to components with lower index). ncomps will contain the number of components. template bool solve() { Time: O (E + V ) 24 lines void bicomps(F f) { values.assign(N, -1); vi val, comp, z, cont; num.assign(sz(ed), 0); val.assign(2*N, 0); comp = val; int Time, ncomps; rep(i,0,sz(ed)) if (!num[i]) dfs(i, -1, f); rep(i,0,2*N) if (!comp[i]) dfs(i); template int dfs(int j, G& g, F f) { } rep(i,0,N) if (comp[2*i] == comp[2*i+1]) return 0; int low = val[j] = ++Time, x; z.push_back(j); return 1; trav(e,g[j]) if (comp[e] < 0) } low = min(low, val[e] ?: dfs(e,g,f)); 2sat.h }; Description: Calculates a valid assignment to boolean variables a, if (low == val[j]) { b, c,... to a 2-SAT problem, so that an expression of the type do { (akkb)&&(!akkc)&&(dkk!b)&&... becomes true, or reports that it is unsatis- ∼x 7.7 Trees x = z.back(); z.pop_back(); fiable. Negated variables are represented by bit-inversions ( ). TwoSat ts(number of boolean variables); comp[x] = ncomps; Usage: ts.either(0, ∼3); // Var 0 is true or var 3 is false cont.push_back(x); TreePower.h ts.set value(2); // Var 2 is true } while (x != j); Description: Calculate power of two jumps in a tree. Assumes the root ts.at most one( 0,∼1,2 ); // = 1 of vars 0, ∼1 and 2 are true f(cont); cont.clear(); { } < node points to itself. ts.solve(); // Returns true iff it is solvable ncomps++; Time: O (|V | log |V |) ts.values[0..N-1] holds the assigned values to the vars 14 lines } vector treeJump(vi& P){ return val[j] = low; Time: O (N + E), where N is the number of boolean variables, and E is the number of clauses. int on = 1, d = 1; } 57 lines while(on < sz(P)) on *= 2, d++; template void scc(G& g, F f) { struct TwoSat { vector jmp(d, P); int n = sz(g); int N; rep(i,1,d) rep(j,0,sz(P)) val.assign(n, 0); comp.assign(n, -1); vector gr; jmp[i][j] = jmp[i-1][jmp[i-1][j]]; Time = ncomps = 0; vi values; // 0= false, 1= true return jmp; rep(i,0,n) if (comp[i] < 0) dfs(i, g, f); } } TwoSat(int n = 0) : N(n), gr(2*n) {} int jmp(vector& tbl, int nod, int steps){ BiconnectedComponents.h int add_var() { // (optional) rep(i,0,sz(tbl)) Description: Finds all biconnected components in an undirected graph, gr.emplace_back(); if(steps&(1<= 0 ? 2*f : -1-2*f); j = (j >= 0 ? 2*j : -1-2*j); in a tree (with 0 as root). C should be an adjacency list of the tree, either ed[a].emplace back(b, eid); directed or undirected. Can also find the distance between two nodes. ed[b].emplace back(a, eid++); } gr[fˆ1].push_back(j); gr[jˆ1].push_back(f); Usage: LCA lca(undirGraph); bicomps([&](const vi& edgelist) {...}); lca.query(firstNode, secondNode); Time: O (E + V ) } 34 lines void set_value(int x) { either(x, x); } lca.distance(firstNode, secondNode); vi num, st; Time: O (|V | log |V | + Q) vector> ed; void at_most_one(const vi& li) { // (optional) "../data-structures/RMQ.h" 38 lines int Time; if (sz(li) <= 1) return; typedef vector vpi; template int cur = ∼li[0]; typedef vector graph; int dfs(int at, int par, F f) { rep(i,2,sz(li)) { const pii inf(1 << 29, -1); int me = num[at] = ++Time, e, y, top = me; int next = add_var(); trav(pa, ed[at]) if (pa.second != par) { either(cur, ∼li[i]); struct LCA { tie(y, e) = pa; either(cur, next); vi time; if (num[y]) { either(∼li[i], next); vector dist; top = min(top, num[y]); cur = ∼next; RMQ rmq; if (num[y] < me) } st.push_back(e); either(cur, ∼li[1]); LCA(graph& C) : time(sz(C), -99), dist(sz(C)), rmq(dfs(C)) {} UiB CompressTree HLD LinkCutTree 16

struct Node { vpi dfs(graph& C) { int d, par, val, chain = -1, pos = -1; pii dfs(int at, int par, vector& g, int d) { vector > q(1); }; V[at].d = d; V[at].par = par; vpi ret; int sum = 1, ch, nod, sz; int T = 0, v, p, d; ll di; struct Chain { tuple mx(-1,-1,-1); while (!q.empty()) { int par, val; trav(e, g[at]){ tie(v, p, d, di) = q.back(); vector nodes; if (e.first == par) continue; q.pop_back(); Tree tree; tie(sz, ch) = dfs(e.first, at, g, d+1); if (d) ret.emplace_back(d, p); }; V[e.first].val = e.second; time[v] = T++; sum += sz; dist[v] = di; struct HLD { mx = max(mx, make_tuple(sz, e.first, ch)); trav(e, C[v]) if (e.first != p) typedef int T; } q.emplace_back(e.first, v, d+1, di + e.second); const T LOW = -(1<<29); tie(sz, nod, ch) = mx; } void f(T& a, T b) { a = max(a, b); } if (2*sz < sum) return pii(sum, -1); return ret; if (ch == -1) { ch = sz(C); C.emplace_back(); } } vector V; V[nod].pos = sz(C[ch].nodes); vector C; V[nod].chain = ch; int query(int a, int b) { C[ch].par = at; if (a == b) return a; HLD(vector& g) : V(sz(g)) { C[ch].nodes.push_back(nod); a = time[a], b = time[b]; dfs(0, -1, g, 0); return pii(sum, ch); return rmq.query(min(a, b), max(a, b)).second; trav(c, C){ } } c.tree.init(sz(c.nodes), 0); }; ll distance(int a, int b) { for (int ni : c.nodes) int lca = query(a, b); c.tree.update(V[ni].pos, V[ni].val); return dist[a] + dist[b] - 2 * dist[lca]; } LinkCutTree.h } } Description: Represents a forest of unrooted trees. You can add and re- }; move edges (as long as the result is still a forest), and check whether two void update(int node, T val) { nodes are in the same tree. Time: All operations take amortized O (log N). Node& n = V[node]; n.val = val; 96 lines if (n.chain != -1) C[n.chain].tree.update(n.pos, val); CompressTree.h struct Node { // Splay tree. Root’s pp contains tree’s parent. Description: Given a rooted tree and a subset S of nodes, compute the } Node p = 0, pp = 0, c[2]; minimal subtree that contains all the nodes by adding all (at most |S| − 1) * * * bool flip = 0; pairwise LCA’s and compressing edges. Returns a list of (par, orig index) int pard(Node& nod) { Node() { c[0] = c[1] = 0; fix(); } representing a tree rooted at 0. The root points to itself. if (nod.par == -1) return -1; void fix() { Time: O (|S| log |S|) return V[nod.chain == -1 ? nod.par : C[nod.chain].par].d; if (c[0]) c[0]->p = this; "LCA.h" 20 lines } if (c[1]) c[1]->p = this; vpi compressTree(LCA& lca, const vi& subset) { // (+ update sum of subtree elements etc. if wanted) static vi rev; rev.resize(sz(lca.dist)); // query a l l ∗edges∗ between n1, n2 } pair query(int i1, int i2) { vi li = subset, &T = lca.time; void push_flip() { T ans = LOW; auto cmp = [&](int a, int b) { return T[a] < T[b]; }; if (!flip) return; while(i1 != i2) { sort(all(li), cmp); flip = 0; swap(c[0], c[1]); Node n1 = V[i1], n2 = V[i2]; int m = sz(li)-1; if (c[0]) c[0]->flip ˆ= 1; if (n1.chain != -1 && n1.chain == n2.chain) { rep(i,0,m) { if (c[1]) c[1]->flip ˆ= 1; int lo = n1.pos, hi = n2.pos; int a = li[i], b = li[i+1]; } if (lo > hi) swap(lo, hi); li.push_back(lca.query(a, b)); int up() { return p ? p->c[1] == this : -1; } f(ans, C[n1.chain].tree.query(lo, hi)); } void rot(int i, int b) { i1 = i2 = C[n1.chain].nodes[hi]; sort(all(li), cmp); int h = i ˆ b; } else { li.erase(unique(all(li)), li.end()); Node x = c[i], y = b == 2 ? x : x->c[h], z = b ? y : x; if (pard(n1) < pard(n2)) * * * rep(i,0,sz(li)) rev[li[i]] = i; if ((y->p = p)) p->c[up()] = y; n1 = n2, swap(i1, i2); vpi ret = {pii(0, li[0])}; c[i] = z->c[i ˆ 1]; if (n1.chain == -1) rep(i,0,sz(li)-1) { if (b < 2) { f(ans, n1.val), i1 = n1.par; int a = li[i], b = li[i+1]; x->c[h] = y->c[h ˆ 1]; else { ret.emplace_back(rev[lca.query(a, b)], b); z->c[h ˆ 1] = b ? x : this; Chain& c = C[n1.chain]; } } f(ans, n1.pos ? c.tree.query(n1.pos, sz(c.nodes)) return ret; y->c[i ˆ 1] = b ? this : x; : c.tree.s[1]); } fix(); x->fix(); y->fix(); i1 = c.par; if (p) p->fix(); } swap(pp, y->pp); } HLD.h } } Description: Decomposes a tree into vertex disjoint heavy paths and light void splay() { return make_pair(ans, i1); edges such that the path from any leaf to the root contains at most log(n) for (push_flip(); p; ) { } light edges. The function of the HLD can be changed by modifying T, LOW if (p->p) p->p->push_flip(); and f. f is assumed to be associative and commutative. p->push_flip(); push_flip(); Usage: HLD hld(G); // query a l l ∗nodes∗ between n1, n2 int c1 = up(), c2 = p->up(); pair query2(int i1, int i2) { hld.update(index, value); if (c2 == -1) p->rot(c1, 2); pair ans = query(i1, i2); tie(value, lca) = hld.query(n1, n2); else p->p->rot(c2, c1 != c2); f(ans.first, V[ans.second].val); "../data-structures/SegmentTree.h" 93 lines } return ans; typedef vector vpi; } } Node* first() { UiB MatrixTree Point lineDistance SegmentDistance SegmentIntersection SegmentIntersectionQ 17

push_flip(); Geometry (8) SegmentIntersection.h return c[0] ? c[0]->first() : (splay(), this); Description: } If a unique intersetion point between the line segments going }; from s1 to e1 and from s2 to e2 exists r1 is set to this point 8.1 Geometric primitives and 1 is returned. If no intersection point exists 0 is returned struct LinkCut { and if infinitely many exists 2 is returned and r1 and r2 are e1 vector node; set to the two ends of the common line. The wrong position e2 LinkCut(int N) : node(N) {} will be returned if P is Point and the intersection point r1 Point.h does not have integer coordinates. Products of three coordi- s1 s2 void link(int u, int v) { // add an edge (u, v) Description: Class to handle points in the plane. T can be e.g. double or nates are used in intermediate steps so watch out for overflow long long. (Avoid int.) assert(!connected(u, v)); 25 lines if using int or long long. Use segmentIntersectionQ to get just make_root(&node[u]); template a true/false answer. Usage: Point intersection, dummy; node[u].pp = &node[v]; struct Point { if (segmentIntersection(s1,e1,s2,e2,intersection,dummy)==1) } typedef Point P; cout << "segments intersect at " << intersection << endl; T x, y; void cut(int u, int v) { // remove an edge (u, v) explicit Point(T x=0, T y=0) : x(x), y(y) {} "Point.h" 27 lines Node *x = &node[u], *top = &node[v]; bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); } template make_root(top); x->splay(); bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); } int segmentIntersection(const P& s1, const P& e1, assert(top == (x->pp ?: x->c[0])); P operator+(P p) const { return P(x+p.x, y+p.y); } const P& s2, const P& e2, P& r1, P& r2) { if (x->pp) x->pp = 0; P operator-(P p) const { return P(x-p.x, y-p.y); } if (e1==s1) { else { P operator*(T d) const { return P(x*d, y*d); } if (e2==s2) { x->c[0] = top->p = 0; P operator/(T d) const { return P(x/d, y/d); } if (e1==e2) { r1 = e1; return 1; } // a l l equal x->fix(); T dot(P p) const { return x*p.x + y*p.y; } else return 0; //different point segments } T cross(P p) const { return x*p.y - y*p.x; } } else return segmentIntersection(s2,e2,s1,e1,r1,r2);//swap } T cross(P a, P b) const { return (a-*this).cross(b-*this); } } T dist2() const { return x*x + y*y; } //segment directions and separation bool connected(int u, int v) { // are u, v in the same tree? double dist() const { return sqrt((double)dist2()); } P v1 = e1-s1, v2 = e2-s2, d = s2-s1; Node* nu = access(&node[u])->first(); // angle to x−axis in interval [−pi , pi ] auto a = v1.cross(v2), a1 = v1.cross(d), a2 = v2.cross(d); return nu == access(&node[v])->first(); double angle() const { return atan2(y, x); } if (a == 0) { //if parallel } P unit() const { return *this/dist(); } // makes dist ()=1 auto b1=s1.dot(v1), c1=e1.dot(v1), P perp() const { return P(-y, x); } // rotates +90 degrees b2=s2.dot(v1), c2=e2.dot(v1); void make_root(Node* u) { P normal() const { return perp().unit(); } if (a1 || a2 || max(b1,min(b2,c2))>min(c1,max(b2,c2))) access(u); // returns point rotated ’a’ radians ccw around the origin return 0; u->splay(); P rotate(double a) const { r1 = min(b2,c2)c[0]) { return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); } r2 = max(b2,c2)>c1 ? e1 : (b2>c2 ? s2 : e2); u->c[0]->p = 0; }; return 2-(r1==r2); u->c[0]->flip ˆ= 1; } u->c[0]->pp = u; if (a < 0) { a = -a; a1 = -a1; a2 = -a2; } u->c[0] = 0; if (0fix(); lineDistance.h return 0; } Description: r1 = s1-v1*a2/a; } Returns the signed distance between point p and the line con- return 1; taining points a and b. Positive value on left side and negative res } Node* access(Node* u) { on right as seen from a towards b. a==b gives nan. P is sup- e p u->splay(); posed to be Point or Point3D where T is e.g. double SegmentIntersectionQ.h while (Node* pp = u->pp) { or long long. It uses products in intermediate steps so watch Description: Like segmentIntersection, but only returns true/false. Prod- pp->splay(); u->pp = 0; out for overflow if using int or long long. Using Point3D will s ucts of three coordinates are used in intermediate steps so watch out for if (pp->c[1]) { always give a non-negative distance. pp->c[1]->p = 0; pp->c[1]->pp = pp; } "Point.h" 4 lines overflow if using int or long long. pp->c[1] = u; pp->fix(); u = pp; template "Point.h" 16 lines } double lineDist(const P& a, const P& b, const P& p) { template return u; return (double)(b-a).cross(p-a)/(b-a).dist(); bool segmentIntersectionQ(P s1, P e1, P s2, P e2) { } } if (e1 == s1) { }; if (e2 == s2) return e1 == e2; swap(s1,s2); swap(e1,e2); } res 7.8 Matrix tree theorem SegmentDistance.h e p P v1 = e1-s1, v2 = e2-s2, d = s2-s1; Description: auto a = v1.cross(v2), a1 = d.cross(v1), a2 = d.cross(v2); Returns the shortest distance between point p and the line if (a == 0) { // parallel MatrixTree.h segment from point s to e. s auto b1 = s1.dot(v1), c1 = e1.dot(v1), Description: To count the number of spanning trees in an undirected Usage: Point a, b(2,2), p(1,1); b2 = s2.dot(v1), c2 = e2.dot(v1); graph G: create an N × N matrix mat, and for each edge (a, b) ∈ G, do bool onSegment = segDist(a,b,p) < 1e-10; return !a1 && max(b1,min(b2,c2)) <= min(c1,max(b2,c2)); mat[a][a]++, mat[b][b]++, mat[a][b]--, mat[b][a]--. Remove the "Point.h" 6 lines } last row and column, and take the determinant. 1 lines typedef Point P; if (a < 0) { a = -a; a1 = -a1; a2 = -a2; } double segDist(P& s, P& e, P& p) { return (0 <= a1 && a1 <= a && 0 <= a2 && a2 <= a); if (s==e) return (p-s).dist(); } auto d = (e-s).dist2(), t = min(d,max(.0,(p-s).dot(e-s))); return ((p-s)*d-(e-s)*t).dist()/d; } UiB lineIntersection sideOf onSegment linearTransformation Angle CircleIntersection circleTangents circumcircle MinimumEnclosingCircle 18 lineIntersection.h Angle.h circleTangents.h Description: Description: A class for ordering angles (as represented by int points and Description: If a unique intersetion point of the lines going through s1,e1 a number of rotations around the origin). Useful for rotational sweeping. Returns a pair of the two points on the circle with radius r second and s2,e2 exists r is set to this point and 1 is returned. If no Usage: vector v = {w[0], w[0].t360() ...}; // sorted centered around c whos tangent lines intersect p. If p lies r intersection point exists 0 is returned and if infinitely many int j = 0; rep(i,0,n) { e2 within the circle NaN-points are returned. P is intended to c exists -1 is returned. If s1==e1 or s2==e2 -1 is returned. The r while (v[j] < v[i].t180()) ++j; be Point. The first point is the one to the right as first wrong position will be returned if P is Point and the in- e1 s2 } // sweeps j such that (j-i) represents the number of seen from the p towards c. p tersection point does not have integer coordinates. Products positively oriented triangles with vertices at 0 and i s1 37 lines Usage: typedef Point P; of three coordinates are used in intermediate steps so watch pair p = circleTangents(P(100,2),P(0,0),2); out for overflow if using int or long long. struct Angle { Usage: point intersection; int x, y; "Point.h" 6 lines if (1 == LineIntersection(s1,e1,s2,e2,intersection)) int t; template cout << "intersection point at " << intersection << endl; Angle(int x, int y, int t=0) : x(x), y(y), t(t) {} pair circleTangents(const P &p, const P &c, double r) { "Point.h" 9 lines Angle operator-(Angle a) const { return {x-a.x, y-a.y, t}; } P a = p-c; int const double x = r r/a.dist2(), y = sqrt(x-x x); template quad() { * * return make_pair(c+a x+a.perp() y, c+a x-a.perp() y); int lineIntersection(const P& s1, const P& e1, const P& s2, assert(x || y); * * * * if return } const P& e2, P& r) { (y < 0) (x >= 0) + 2; if (y > 0) return (x <= 0); if ((e1-s1).cross(e2-s2)) { //if not parallell return r = s2-(e2-s2) (e1-s1).cross(s2-s1)/(e1-s1).cross(e2-s2); (x <= 0) * 2; * } circumcircle.h return 1; Description: const return } else Angle t90() { {-y, x, t + (quad() == 3)}; } const return The circumcirle of a triangle is the circle intersecting all B return -((e1-s1).cross(s2-s1)==0 || s2==e2); Angle t180() { {-x, -y, t + (quad() >= 2)}; } const return three vertices. ccRadius returns the radius of the circle going r c } Angle t360() { {x, y, t + 1}; } }; through points A, B and C and ccCenter returns the center C bool operator<(Angle a, Angle b) { of the same circle. A sideOf.h // add a.dist2() and b.dist2() to also compare distances "Point.h" 9 lines Description: Returns where p is as seen from s towards e. 1/0/-1 ⇔ return make_tuple(a.t, a.quad(), a.y * (ll)b.x) < typedef Point P; left/on line/right. If the optional argument eps is given 0 is returned if p is make_tuple(b.t, b.quad(), a.x * (ll)b.y); double ccRadius(const P& A, const P& B, const P& C) { within distance eps from the line. P is supposed to be Point where T } return (B-A).dist()*(C-B).dist()*(A-C).dist()/ is e.g. double or long long. It uses products in intermediate steps so watch bool operator>=(Angle a, Angle b) { return !(a < b); } abs((B-A).cross(C-A))/2; out for overflow if using int or long long. bool operator>(Angle a, Angle b) { return b < a; } } Usage: bool left = sideOf(p1,p2,q)==1; bool operator<=(Angle a, Angle b) { return !(b < a); } P ccCenter(const P& A, const P& B, const P& C) { "Point.h" 11 lines P b = C-A, c = B-A; template // Given two points, this calculates the smallest angle between return A + (b*c.dist2()-c*b.dist2()).perp()/b.cross(c)/2; int sideOf(const P& s, const P& e, const P& p) { // them, i.e., the angle that covers the defined line segment. } auto a = (e-s).cross(p-s); pair segmentAngles(Angle a, Angle b) { if (b < a) swap(a, b); return (a > 0) - (a < 0); MinimumEnclosingCircle.h } return (b < a.t180() ? make_pair(a, b) : make_pair(b, a.t360())); Description: Computes the minimum circle that encloses a set of points. template Time: expected O (n) int sideOf(const P& s, const P& e, const P& p, double eps) { } "circumcircle.h" 28 lines auto a = (e-s).cross(p-s); Angle operator+(Angle a, Angle b) { // where b is a vector pair mec2(vector

& S, P a, P b, int n) { double l = (e-s).dist()*eps; return (a > l) - (a < -l); Angle r(a.x + b.x, a.y + b.y, a.t); double hi = , lo = -hi; } if (r > a.t180()) r.t--; rep(i,0,n) { return r.t180() < a ? r.t360() : r; auto si = (b-a).cross(S[i]-a); } if (si == 0) continue; onSegment.h P m = ccCenter(a, b, S[i]); Description: Returns true iff p lies on the line segment from s to e. In- auto cr = (b-a).cross(m-a); tended for use with e.g. Point where overflow is an issue. Use 8.2 Circles if (si < 0) hi = min(hi, cr); (segDist(s,e,p)<=epsilon) instead when using Point. else lo = max(lo, cr); "Point.h" 5 lines } template CircleIntersection.h double v = (0 < lo ? lo : hi < 0 ? hi : 0); bool onSegment(const P& s, const P& e, const P& p) { Description: Computes a pair of points at which two circles intersect. P c = (a + b) / 2 + (b - a).perp() * v / (b - a).dist2(); P ds = p-s, de = p-e; Returns false in case of no intersection. return {(a - c).dist2(), c}; return ds.cross(de) == 0 && ds.dot(de) <= 0; "Point.h" 14 lines } } typedef Point P; pair mec(vector

& S, P a, int n) { bool circleIntersection(P a, P b, double r1, double r2, random_shuffle(S.begin(), S.begin() + n); P b = S[0], c = (a + b) / 2; r p1 pair* out) { linearTransformation.h P delta = b - a; double r = (a - c).dist2(); Description: rep(i,1,n) if ((S[i] - c).dist2() > r * (1 + 1e-8)) { p0 res assert(delta.x || delta.y || r1 != r2); if (!delta.x && !delta.y) return false; tie(r,c) = (n == sz(S) ? Apply the linear transformation (translation, rotation and q0 scaling) which takes line p0-p1 to line q0-q1 to point r. double r = r1 + r2, d2 = delta.dist2(); mec(S, S[i], i) : mec2(S, a, S[i], i)); q1 } "Point.h" 6 lines double p = (d2 + r1*r1 - r2*r2) / (2.0 * d2); double h2 = r1 r1 - p p d2; return {r, c}; typedef Point P; * * * if (d2 > r r || h2 < 0) return false; } P linearTransformation(const P& p0, const P& p1, * P mid = a + delta p, per = delta.perp() sqrt(h2 / d2); pair enclosingCircle(vector

S) { const P& q0, const P& q1, const P& r) { * * out = {mid + per, mid - per}; assert(!S.empty()); auto r = mec(S, S[0], sz(S)); P dp = p1-p0, dq = q1-q0, num(dp.cross(dq), dp.dot(dq)); * return true; return {sqrt(r.first), r.second}; return q0 + P((r-p0).cross(num), (r-p0).dot(num))/dp.dist2(); } } } UiB insidePolygon PolygonArea PolygonCenter PolygonCut ConvexHull PolygonDiameter PointInsideHull LineHullIntersection 19

8.3 Polygons vector

res; PointInsideHull.h rep(i,0,sz(poly)) { Description: Determine whether a point t lies inside a given polygon P cur = poly[i], prev = i ? poly[i-1] : poly.back(); (counter-clockwise order). The polygon must be such that every point on insidePolygon.h bool side = s.cross(e, cur) < 0; the circumference is visible from the first point in the vector. It returns 0 Description: Returns true if p lies within the polygon described by the if (side != (s.cross(e, prev) < 0)) { for points outside, 1 for points on the circumference, and 2 for points inside. points between iterators begin and end. If strict false is returned when p is res.emplace_back(); Time: O (log N) on the edge of the polygon. Answer is calculated by counting the number of lineIntersection(s, e, cur, prev, res.back()); "Point.h", "sideOf.h", "onSegment.h" 22 lines intersections between the polygon and a line going from p to infinity in the } typedef Point P; positive x-direction. The algorithm uses products in intermediate steps so if (side) watch out for overflow. If points within epsilon from an edge should be con- int insideHull2(const vector

& H, int L, int R, const P& p) { res.push_back(cur); int len = R - L; sidered as on the edge replace the line ”if (onSegment...” with the comment } bellow it (this will cause overflow for int and long long). if (len == 2) { return res; int sa = sideOf(H[0], H[L], p); Usage: typedef Point pi; } vector v; v.push back(pi(4,4)); int sb = sideOf(H[L], H[L+1], p); v.push back(pi(1,2)); v.push back(pi(2,1)); int sc = sideOf(H[L+1], H[0], p); bool in = insidePolygon(v.begin(),v.end(), pi(3,4), false); if (sa < 0 || sb < 0 || sc < 0) return 0; Time: O (n) ConvexHull.h if (sb==0 || (sa==0 && L == 1) || (sc == 0 && R == sz(H))) return "Point.h", "onSegment.h", "SegmentDistance.h" 14 lines Description: 1; Returns a vector of indices of the convex hull in counter- return 2; template class class < It, P> clockwise order. Points on the edge of the hull between two } bool const insidePolygon(It begin, It end, P& p, other points are not considered part of the hull. int mid = L + len / 2; bool true strict = ){ Usage: vector

ps, hull; if (sideOf(H[0], H[mid], p) >= 0) int n = 0; //number of isects with line from p to (inf,p.y) trav(i, convexHull(ps)) hull.push back(ps[i]); return insideHull2(H, mid, R, p); for (It i = begin, j = end-1; i != end; j = i++) { Time: O (n log n) return insideHull2(H, L, mid+1, p); //if p is on edge of polygon "Point.h" 20 lines } if (onSegment( i, j, p)) return !strict; * * typedef Point P; //or: if (segDist(∗i , ∗j , p) <= epsilon) return !strict; pair ulHull(const vector

& S) { int insideHull(const vector

& hull, const P& p) { //increment n if segment intersects line from p vi Q(sz(S)), U, L; if (sz(hull) < 3) return onSegment(hull[0], hull.back(), p); n += (max(i->y,j->y) > p.y && min(i->y,j->y) <= p.y && iota(all(Q), 0); else return insideHull2(hull, 1, sz(hull), p); (( j- i).cross(p- i) > 0) == (i->y <= p.y)); * * * sort(all(Q), [&S](int a, int b){ return S[a] < S[b]; }); } } trav(it, Q) { return n&1; //inside if odd number of intersections #define ADDP(C, cmp) while (sz(C) > 1 && S[C[sz(C)-2]].cross(\ } S[it], S[C.back()]) cmp 0) C.pop_back(); C.push_back(it); LineHullIntersection.h ADDP(U, <=); ADDP(L, >=); Description: Line-convex polygon intersection. The polygon must be ccw PolygonArea.h } and have no colinear points. isct(a, b) returns a pair describing the inter- Description: Returns twice the signed area of a polygon. Clockwise enu- return {U, L}; section of a line with the polygon: • (−1, −1) if no collision, • (i, −1) if meration gives negative area. Watch out for overflow if using int as T! } touching the corner i, • (i, i) if along side (i, i + 1), • (i, j) if crossing sides "Point.h" 6 lines (i, i + 1) and (j, j + 1). In the last case, if a corner i is crossed, this is treated template vi convexHull(const vector

& S) { as happening on side (i, i + 1). The points are returned in the same order as T polygonArea2(vector>& v) { vi u, l; tie(u, l) = ulHull(S); the line hits the polygon. T a = v.back().cross(v[0]); if (sz(S) <= 1) return u; Time: O (N + Q log n) rep(i,0,sz(v)-1) a += v[i].cross(v[i+1]); if (S[u[0]] == S[u[1]]) return {0}; "Point.h" 63 lines return a; l.insert(l.end(), u.rbegin()+1, u.rend()-1); ll sgn(ll a) { return (a > 0) - (a < 0); } } return l; typedef Point P; } struct HullIntersection { int N; PolygonCenter.h vector

p; Description: Returns the center of mass for a polygon. PolygonDiameter.h vector> a; "Point.h" 10 lines Description: Calculates the max squared distance of a set of points. typedef Point P; "ConvexHull.h" 19 lines HullIntersection(const vector

& ps) : N(sz(ps)), p(ps) { p.insert(p.end(), all(ps)); Point polygonCenter(vector

& v) { vector antipodal(const vector

& S, vi& U, vi& L) { int b = 0; auto i = v.begin(), end = v.end(), j = end-1; vector ret; rep(i,1,N) if (P{p[i].y,p[i].x} < P{p[b].y, p[b].x}) b = i; Point res{0,0}; double A = 0; int i = 0, j = sz(L) - 1; rep(i,0,N) { for (; i != end; j=i++) { while (i < sz(U) - 1 || j > 0) { int f = (i + b) % N; res = res + (*i + *j) * j->cross(*i); ret.emplace_back(U[i], L[j]); a.emplace_back(p[f+1] - p[f], f); A += j->cross(*i); if (j == 0 || (i != sz(U)-1 && (S[L[j]] - S[L[j-1]]) } } .cross(S[U[i+1]] - S[U[i]]) > 0)) ++i; } return res / A / 3; else --j; } } int qd(P p) { return ret; return (p.y < 0) ? (p.x >= 0) + 2 e } PolygonCut.h : (p.x <= 0) * (1 + (p.y <= 0)); Description: } Returns a vector with the vertices of a polygon with every- pii polygonDiameter(const vector

& S) { vi U, L; tie(U, L) = ulHull(S); thing to the left of the line going from s to e cut away. int bs(P dir) { pair ans; Usage: vector

p = ...; int lo = -1, hi = N; s trav(x, antipodal(S, U, L)) p = polygonCut(p, P(0,0), P(1,0)); while (hi - lo > 1) { ans = max(ans, {(S[x.first] - S[x.second]).dist2(), x}); "Point.h", "lineIntersection.h" 15 lines int mid = (lo + hi) / 2; return ans.second; typedef Point P; if (make_pair(qd(dir), dir.y a[mid].first.x) < } * vector

polygonCut(const vector

& poly, P s, P e) { make_pair(qd(a[mid].first), dir.x * a[mid].first.y)) UiB closestPair kdTree DelaunayTriangulation PolyhedronVolume 20

hi = mid; if(*i != xa[split] && (**i-splitp).dist2() < 1e-12) int half = sz(vp)/2; else lo = mid; return i1 = *i, i2 = xa[split], 0;// nasty special case! first = new Node({vp.begin(), vp.begin() + half}); } if (**i < splitp) ly.push_back(*i); second = new Node({vp.begin() + half, vp.end()}); return a[hi%N].second; else ry.push_back(*i); } } } // assert((signed)lefty.size() == split) } It j1, j2; // Conquer }; bool isign(P a, P b, int x, int y, int s) { double a = cp_sub(ly.begin(), ly.end(), xa, i1, i2); return sgn(a.cross(p[x], b)) * sgn(a.cross(p[y], b)) == s; double b = cp_sub(ry.begin(), ry.end(), xa+split, j1, j2); struct KDTree { } if(b < a) a = b, i1 = j1, i2 = j2; Node* root; double a2 = a*a; KDTree(const vector

& vp) : root(new Node({all(vp)})) {} int bs2(int lo, int hi, P a, P b) { for(IIt i = ya; i != yaend; ++i) { // Create strip (y−sorted) int L = lo; double x = (*i)->x; pair search(Node *node, const P& p) { if (hi < lo) hi += N; if(x >= splitx-a && x <= splitx+a) stripy.push_back(*i); if (!node->first) { while (hi - lo > 1) { } // uncomment if we should not find the point itself: int mid = (lo + hi) / 2; for(IIt i = stripy.begin(); i != stripy.end(); ++i) { // i f (p == node−>pt) return {INF, P() }; if (isign(a, b, mid, L, -1)) hi = mid; const P &p1 = **i; return make_pair((p - node->pt).dist2(), node->pt); else lo = mid; for(IIt j = i+1; j != stripy.end(); ++j) { } } const P &p2 = **j; return lo; if(p2.y-p1.y > a) break; Node *f = node->first, *s = node->second; } double d2 = (p2-p1).dist2(); T bfirst = f->distance(p), bsec = s->distance(p); if(d2 < a2) i1 = *i, i2 = *j, a2 = d2; if (bfirst > bsec) swap(bsec, bfirst), swap(f, s); pii isct(P a, P b) { }} int f = bs(a - b), j = bs(b - a); return sqrt(a2); // search closest side first, other side if needed if (isign(a, b, f, j, 1)) return {-1, -1}; } auto best = search(f, p); int x = bs2(f, j, a, b)%N, if (bsec < best.first) y = bs2(j, f, a, b)%N; template // It is random access iterators of point best = min(best, search(s, p)); if (a.cross(p[x], b) == 0 && double closestpair(It begin, It end, It &i1, It &i2 ) { return best; a.cross(p[x+1], b) == 0) return {x, x}; vector xa, ya; } if (a.cross(p[y], b) == 0 && assert(end-begin >= 2); a.cross(p[y+1], b) == 0) return {y, y}; for (It i = begin; i != end; ++i) // find nearest point to a point, and its squared distance if (a.cross(p[f], b) == 0) return {f, -1}; xa.push_back(i), ya.push_back(i); // (requires an arbitrary operator< for Point) if (a.cross(p[j], b) == 0) return {j, -1}; sort(xa.begin(), xa.end(), it_less); pair nearest(const P& p) { return {x, y}; sort(ya.begin(), ya.end(), y_it_less); return search(root, p); } return cp_sub(ya.begin(), ya.end(), xa.begin(), i1, i2); } }; } };

DelaunayTriangulation.h 8.4 Misc. Point Set Problems kdTree.h Description: Computes the Delaunay triangulation of a set of points. Description: KD-tree (2d, can be extended to 3d) Each circumcircle contains none of the input points. If any three points are "Point.h" 63 lines colinear or any four are on the same circle, behavior is undefined. closestPair.h typedef long long T; Time: O n2 Description: i1, i2 are the indices to the closest pair of points in the point typedef Point P; "Point.h", "3dHull.h" 10 lines vector p after the call. The distance is returned. const T INF = numeric_limits::max(); template Time: O (n log n) void delaunay(vector

& ps, F trifun) { "Point.h" 58 lines bool on_x(const P& a, const P& b) { return a.x < b.x; } if (sz(ps) == 3) { int d = (ps[0].cross(ps[1], ps[2]) < 0); template bool on_y(const P& a, const P& b) { return a.y < b.y; } trifun(0,1+d,2-d); } bool it_less(const It& i, const It& j) { return *i < *j; } vector p3; template struct Node { trav(p, ps) p3.emplace_back(p.x, p.y, p.dist2()); bool y_it_less(const It& i,const It& j) {return i->y < j->y;} P pt; // if this is a leaf, the single point in it if (sz(ps) > 3) trav(t, hull3d(p3)) if ((p3[t.b]-p3[t.a]). T x0 = INF, x1 = -INF, y0 = INF, y1 = -INF; // bounds cross(p3[t.c]-p3[t.a]).dot(P3(0,0,1)) < 0) template /∗ IIt = vector:: iterator ∗/ Node *first = 0, *second = 0; trifun(t.a, t.c, t.b); double cp_sub(IIt ya, IIt yaend, IIt xa, It &i1, It &i2) { } typedef typename iterator_traits::value_type P; T distance(const P& p) { // min squared distance to a point int n = yaend-ya, split = n/2; T x = (p.x < x0 ? x0 : p.x > x1 ? x1 : p.x); if(n <= 3) { // base case T y = (p.y < y0 ? y0 : p.y > y1 ? y1 : p.y); 8.5 3D double a = (*xa[1]-*xa[0]).dist(), b = 1e50, c = 1e50; return (P(x,y) - p).dist2(); if(n==3) b=(*xa[2]-*xa[0]).dist(), c=(*xa[2]-*xa[1]).dist() } ; PolyhedronVolume.h if(a <= b) { i1 = xa[1]; Node(vector

&& vp) : pt(vp[0]) { Description: Magic formula for the volume of a polyhedron. Faces should point outwards. if(a <= c) return i2 = xa[0], a; for (P p : vp) { 6 lines else return i2 = xa[2], c; x0 = min(x0, p.x); x1 = max(x1, p.x); template } else { i1 = xa[2]; y0 = min(y0, p.y); y1 = max(y1, p.y); double signed_poly_volume(const V& p, const L& trilist) { if(b <= c) return i2 = xa[0], b; } double v = 0; else return i2 = xa[1], c; if (vp.size() > 1) { trav(i, trilist) v += p[i.a].cross(p[i.b]).dot(p[i.c]); }} // split on x if the box is wider than high (not best return v / 6; vector ly, ry, stripy; heuristic...) } P splitp = *xa[split]; sort(all(vp), x1 - x0 >= y1 - y0 ? on_x : on_y); double splitx = splitp.x; // divide by taking half the array for each child (not for(IIt i = ya; i != yaend; ++i) { // Divide // best performance with many duplicates in the middle) UiB Point3D 3dHull sphericalDistance KMP Manacher MinRotation SuffixArray 21 Point3D.h Manacher.h Description: Class to handle points in 3D space. T can be e.g. double or rep(i,4,sz(A)) { Description: For each position in a string, computes p[0][i] = half length long long. rep(j,0,sz(FS)) { of longest even palindrome around pos i, p[1][i] = longest odd (half rounded 32 lines F f = FS[j]; down). template struct Point3D { if(f.q.dot(A[i]) > f.q.dot(A[f.a])) { Time: O (N) 11 lines typedef Point3D P; E(a,b).rem(f.c); typedef const P& R; E(a,c).rem(f.b); void manacher(const string& s) { T x, y, z; E(b,c).rem(f.a); int n = sz(s); explicit Point3D(T x=0, T y=0, T z=0) : x(x), y(y), z(z) {} swap(FS[j--], FS.back()); vi p[2] = {vi(n+1), vi(n)}; bool operator<(R p) const { FS.pop_back(); rep(z,0,2) for (int i=0,l=0,r=0; i < n; i++) { return tie(x, y, z) < tie(p.x, p.y, p.z); } } int t = r-i+!z; bool operator==(R p) const { } if (i=1 && R+1r) l=L, r=R; P operator/(T d) const { return P(x/d, y/d, z/d); } C(a, b, c); C(a, c, b); C(b, c, a); }} T dot(R p) const { return x*p.x + y*p.y + z*p.z; } } P cross(R p) const { } MinRotation.h return P(y*p.z - z*p.y, z*p.x - x*p.z, x*p.y - y*p.x); trav(it, FS) if ((A[it.b] - A[it.a]).cross( Description: Finds the lexicographically smallest rotation of a string. } A[it.c] - A[it.a]).dot(it.q) <= 0) swap(it.c, it.b); Usage: rotate(v.begin(), v.begin()+min rotation(v), v.end()); T dist2() const { return x*x + y*y + z*z; } return FS; Time: O (N) double dist() const { return sqrt((double)dist2()); } }; 8 lines //Azimuthal angle (longitude) to x−axis in interval [−pi , pi ] int min_rotation(string s) { double phi() const { return atan2(y, x); } int a=0, N=sz(s); s += s; //Zenith angle (latitude) to the z−axis in interval [0, pi] sphericalDistance.h rep(b,0,N) rep(i,0,N) { double theta() const { return atan2(sqrt(x*x+y*y),z); } Description: Returns the shortest distance on the sphere with radius ra- if (a+i == b || s[a+i] < s[b+i]) {b += max(0, i-1); break;} P unit() const { return *this/(T)dist(); } //makes dist ()=1 dius between the points with azimuthal angles (longitude) f1 (φ1) and f2 (φ2) if (s[a+i] > s[b+i]) { a = b; break;} //returns unit vector normal to ∗this and p from x axis and zenith angles (latitude) t1 (θ1) and t2 (θ2) from z axis. All } P normal(P p) const { return cross(p).unit(); } angles measured in radians. The algorithm starts by converting the spheri- return a; //returns point rotated ’angle’ radians ccw around axis cal coordinates to cartesian coordinates so if that is what you have you can } P rotate(double angle, P axis) const { use only the two last rows. dx*radius is then the difference between the double s = sin(angle), c = cos(angle); P u = axis.unit(); two points in the x direction and d*radius is the total distance between the return u dot(u) (1-c) + ( this) c - cross(u) s; points. * * * * * 8 lines SuffixArray.h } double double double Description: Builds suffix array for a string. a[i] is the starting index of }; sphericalDistance( f1, t1, double f2, double t2, double radius) { the suffix which is i-th in the sorted suffix array. The returned vector is of size n+1, and a[0] = n. The lcp function calculates longest common prefixes double dx = sin(t2)*cos(f2) - sin(t1)*cos(f1); for neighbouring strings in suffix array. The returned vector is of size n + 1, 3dHull.h double dy = sin(t2)*sin(f2) - sin(t1)*sin(f1); Description: Computes all faces of the 3-dimension hull of a point set. double dz = cos(t2) - cos(t1); and ret[0] = 0. Memory: O (N) *No four points must be coplanar*, or else random results will be returned. double d = sqrt(dx*dx + dy*dy + dz*dz); Time: O N log2 N where N is the length of the string for creation of the All faces will point outwards. return radius*2*asin(d/2); 2 SA. O (N) for longest common prefixes. Time: O n } 61 lines "Point3D.h" 49 lines typedef pair pli; typedef Point3D P3; void count_sort(vector &b, int bits) { // (optional) Strings (9) //this is just 3 times faster than stl sort for N=10ˆ6 struct PR { int mask = (1 << bits) - 1; void ins(int x) { (a == -1 ? a : b) = x; } KMP.h rep(it,0,2) { void rem(int x) { (a == x ? a : b) = -1; } Description: pi[x] computes the length of the longest prefix of s that ends int move = it * bits; int cnt() { return (a != -1) + (b != -1); } at x, other than s[0..x] itself This is used by find to find all occurances of a vi q(1 << bits), w(sz(q) + 1); int a, b; string. rep(i,0,sz(b)) }; Usage: vi p = pi(pattern); vi occ = find(word, p); q[(b[i].first >> move) & mask]++; Time: O (pattern) for pi, O (word + pattern) for find partial_sum(q.begin(), q.end(), w.begin() + 1); struct F { P3 q; int a, b, c; }; 16 lines vector res(b.size()); vi pi(const string& s) { rep(i,0,sz(b)) vector hull3d(const vector& A) { vi p(sz(s)); res[w[(b[i].first >> move) & mask]++] = b[i]; assert(sz(A) >= 4); rep(i,1,sz(s)) { swap(b, res); vector> E(sz(A), vector(sz(A), {-1, -1})); int g = p[i-1]; } #define E(x,y) E[f.x][f.y] while (g && s[i] != s[g]) g = p[g-1]; } vector FS; p[i] = g + (s[i] == s[g]); struct SuffixArray { auto mf = [&](int i, int j, int k, int l) { } vi a; P3 q = (A[j] - A[i]).cross((A[k] - A[i])); return p; string s; if (q.dot(A[l]) > q.dot(A[i])) } SuffixArray(const string& _s) : s(_s + ’\0’) { q = q * -1; int N = sz(s); F f{q, i, j, k}; vi match(const string& s, const string& pat) { vector b(N); E(a,b).ins(k); E(a,c).ins(j); E(b,c).ins(i); vi p = pi(pat + ’\0’ + s), res; a.resize(N); FS.push_back(f); rep(i,sz(p)-sz(s),sz(p)) rep(i,0,N) { }; if (p[i] == sz(pat)) res.push_back(i - 2 * sz(pat)); b[i].first = s[i]; rep(i,0,4) rep(j,i+1,4) rep(k,j+1,4) return res; b[i].second = i; mf(i, j, k, 6 - i - j - k); } } UiB SuffixTree Hashing AhoCorasick 22

memset(s, 0, sizeof s); H hashString(string& s) { int q = 8; memset(t, -1, sizeof t); K h = 0; while ((1 << q) < N) q++; fill(t[1],t[1]+ALPHA,0); trav(c, s) h = h * C + c; for (int moc = 0;; moc++) { s[0] = 1; l[0] = l[1] = -1; r[0] = r[1] = p[0] = p[1] = 0; return h - 0; count_sort(b, q); // sort(all(b)) can be used as well rep(i,0,sz(a)) ukkadd(i, toi(a[i])); } a[b[0].second] = 0; } rep(i,1,N) a[b[i].second] = a[b[i - 1].second] + // example: find longest common substring (uses ALPHA= 28) AhoCorasick.h (b[i - 1].first != b[i].first); pii best; Description: Aho-Corasick tree is used for multiple pattern matching. Ini- int lcs(int node, int i1, int i2, int olen) { tialize the tree with create(patterns). find(word) returns for each position if ((1 << moc) >= N) break; if (l[node] <= i1 && i1 < r[node]) return 1; the index of the longest√ word that ends there, or -1 if none. findAll( , word) rep(i,0,N) { if (l[node] <= i2 && i2 < r[node]) return 2; finds all words (up to N N many if no duplicate patterns) that start at each b[i].first = (ll)a[i] << q; int mask = 0, len = node ? olen + (r[node] - l[node]) : 0; position (shortest first). Duplicate patterns are allowed; empty patterns are if (i + (1 << moc) < N) rep(c,0,ALPHA) if (t[node][c] != -1) not. To find the longest words that start at each position, reverse all input. b[i].first += a[i + (1 << moc)]; mask |= lcs(t[node][c], i1, i2, len); Time: Function create is O (26N) where N is the sum of length of patterns. find is O (M) where M is the length of the word. findAll is O (NM). b[i].second = i; if (mask == 3) 67 lines } best = max(best, {len, r[node] - len}); struct AhoCorasick { } return mask; enum {alpha = 26, first = ’A’}; rep(i,0,sz(a)) a[i] = b[i].second; } struct Node { } static pii LCS(string s, string t) { // (nmatches is optional) vi lcp() { SuffixTree st(s + (char)(’z’ + 1) + t + (char)(’z’ + 2)); int back, next[alpha], start = -1, end = -1, nmatches = 0; st.lcs(0, sz(s), sz(s) + 1 + sz(t), 0); // longest common prefixes: res[i] = lcp(a[i], a[i −1]) Node(int v) { memset(next, v, sizeof(next)); } int n = sz(a), h = 0; return st.best; }; vi inv(n), res(n); } vector N; rep(i,0,n) inv[a[i]] = i; }; vector backp; rep(i,0,n) if (inv[i] > 0) { void insert(string& s, int j) { int p0 = a[inv[i] - 1]; assert(!s.empty()); while (s[i + h] == s[p0 + h]) h++; Hashing.h int n = 0; res[inv[i]] = h; Description: Various self-explanatory methods for string hashing. 45 lines trav(c, s) { if(h > 0) h--; typedef unsigned long long H; int& m = N[n].next[c - first]; } static const H C = 123891739; // arbitrary if (m == -1) { n = m = sz(N); N.emplace_back(-1); } return res; else n = m; } // Arithmetic mod 2ˆ64−1. 5x slower than mod 2ˆ64 and more } }; // code, but works on evil test data (e.g. Thue−Morse) . if (N[n].end == -1) N[n].start = j; // ”typedef HK;” instead if you think test data is random. backp.push_back(N[n].end); SuffixTree.h struct K{ N[n].end = j; Description: Ukkonen’s algorithm for online suffix tree construction. Each typedef __uint128_t H2; N[n].nmatches++; node contains indices [l, r) into the string, and a list of child nodes. Suffixes H x; K(H x=0) : x(x) {} } are given by traversals of this tree, joining [l, r) substrings. The root is 0 (has K operator+(K o){ return x + o.x + H(((H2)x + o.x)>>64); } AhoCorasick(vector& pat) { l = -1, r = 0), non-existent children are -1. To get a complete tree, append K operator*(K o){ return K(x*o.x)+ H(((H2)x * o.x)>>64); } N.emplace_back(-1); a dummy symbol – otherwise it may contain an incomplete path (still useful H operator-(K o) { K a = *this + ∼o.x; return a.x + !∼a.x; } rep(i,0,sz(pat)) insert(pat[i], i); for substring matching, though). }; N[0].back = sz(N); Time: O (26N) N.emplace_back(0); 50 lines struct HashInterval { struct SuffixTree { vector ha, pw; queue q; enum { N = 200010, ALPHA = 26 }; // N ∼ 2∗maxlen+10 HashInterval(string& str) : ha(sz(str)+1), pw(ha) { for (q.push(0); !q.empty(); q.pop()) { int toi(char c) { return c - ’a’; } pw[0] = 1; int n = q.front(), prev = N[n].back; string a; // v = cur node, q = cur position rep(i,0,sz(str)) rep(i,0,alpha) { int t[N][ALPHA],l[N],r[N],p[N],s[N],v=0,q=0,m=2; ha[i+1] = ha[i] * C + str[i], int &ed = N[n].next[i], y = N[prev].next[i]; pw[i+1] = pw[i] * C; if (ed == -1) ed = y; void ukkadd(int i, int c) { suff: } else { if (r[v]<=q) { H hashInterval(int a, int b) { // hash [a, b) N[ed].back = y; if (t[v][c]==-1) { t[v][c]=m; l[m]=i; return ha[b] - ha[a] * pw[b - a]; (N[ed].end == -1 ? N[ed].end : backp[N[ed].start]) p[m++]=v; v=s[v]; q=r[v]; goto suff; } } = N[y].end; v=t[v][c]; q=l[v]; }; N[ed].nmatches += N[y].nmatches; } q.push(ed); if (q==-1 || c==toi(a[q])) q++; else { vector getHashes(string& str, int length) { } l[m+1]=i; p[m+1]=m; l[m]=l[v]; r[m]=q; if (sz(str) < length) return {}; } p[m]=p[v]; t[m][c]=m+1; t[m][toi(a[q])]=v; K h = 0, pw = 1; } l[v]=q; p[v]=m; t[p[m]][toi(a[l[m]])]=m; rep(i,0,length) } v=s[p[m]]; q=l[m]; h = h * C + str[i], pw = pw * C; vi find(string word) { while (q ret = {h - 0}; int n = 0; if (q==r[m]) s[m]=v; else s[m]=m+2; rep(i,length,sz(str)) { vi res; // ll count = 0; q=r[v]-(q-r[m]); m+=2; goto suff; ret.push_back(h * C + str[i] - pw * str[i-length]); trav(c, word) { } h = ret.back(); n = N[n].next[c - first]; } } res.push_back(N[n].end); return ret; // count += N[n] . nmatches; SuffixTree(string a) : a(a) { } } fill(r,r+N,sz(a)); return res; UiB IntervalContainer IntervalCover ConstantIntervals TernarySearch Karatsuba LIS LCS 23

} while (at < sz(I) && I[S[at]].first <= cur) { Karatsuba.h vector findAll(vector& pat, string word) { mx = max(mx, make_pair(I[S[at]].second, S[at])); Description: Faster-than-naive convolution of two : c[x] = vi r = find(word); at++; P a[i]b[x − i]. Uses the identity (aX + b)(cX + d) = acX2 + bd + ((a + vector res(sz(word)); } c)(b + d) − ac − bd)X. Doesn’t handle sequences of very different length well. rep(i,0,sz(word)) { if (mx.second == -1) return {}; See also FFT, under the Numerical chapter. int ind = r[i]; cur = mx.first; Time: O N 1.6 1 lines while (ind != -1) { R.push_back(mx.second); res[i - sz(pat[ind]) + 1].push_back(ind); } ind = backp[ind]; return R; LIS.h } } Description: Compute indices for the longest increasing subsequence. } Time: O (N log N) return res; 17 lines } template vi lis(vector S) { }; ConstantIntervals.h vi prev(sz(S)); Description: Split a monotone function on [from, to) into a minimal set typedef pair p; of half-open intervals on which it has the same value. Runs a callback g for vector

res; each such interval. rep(i,0,sz(S)) { Various (10) constantIntervals(0, sz(v), [&](int x) return v[x]; , Usage: { } p el { S[i], i }; [&](int lo, int hi, T val){...}); //S[ i]+1 for non−decreasing Time: O k log n  10.1 Intervals k 19 lines auto it = lower_bound(all(res), p { S[i], 0 }); template if (it == res.end()) res.push_back(el), it = --res.end(); IntervalContainer.h void rec(int from, int to, F f, G g, int& i, T& p, T q) { *it = el; if (p == q) return; prev[i] = it==res.begin() ?0:(it-1)->second; Description: Add and remove intervals from a set of disjoint intervals. } Will merge the added interval with any overlapping intervals in the set when if (from == to) { g(i, to, p); int L = sz(res), cur = res.back().second; adding. Intervals are [inclusive, exclusive). vi ans(L); Time: O (log N) i = to; p = q; 25 lines } else { while (L--) ans[L] = cur, cur = prev[cur]; template int mid = (from + to) >> 1; return ans; auto addInterval(set>& is, T L, T R) { rec(from, mid, f, g, i, p, f(mid)); } if (L == R) return is.end(); rec(mid+1, to, f, g, i, p, q); auto it = is.lower_bound({L, R}), before = it; } LCS.h while (it != is.end() && it->first <= R) { } Description: Finds the longest common subsequence. R = max(R, it->second); template Memory: O (nm). before = it = is.erase(it); void constantIntervals(int from, int to, F f, G g) { Time: O (nm) where n and m are the lengths of the sequences. } if (to <= from) return; 14 lines if (it != is.begin() && (--it)->second >= L) { int i = from; auto p = f(i), q = f(to-1); template T lcs(const T &X, const T &Y) { L = min(L, it->first); rec(from, to-1, f, g, i, p, q); int a = sz(X), b = sz(Y); R = max(R, it->second); g(i, to, q); vector dp(a+1, vi(b+1)); is.erase(it); } rep(i,1,a+1) rep(j,1,b+1) } dp[i][j] = X[i-1]==Y[j-1] ? dp[i-1][j-1]+1 : return is.insert(before, {L,R}); max(dp[i][j-1],dp[i-1][j]); }; int len = dp[a][b]; T ans(len,0); template while(a && b) void removeInterval(set>& is, T L, T R) { if(X[a-1]==Y[b-1]) ans[--len] = X[--a], --b; if (L == R) return; 10.2 Misc. algorithms else if(dp[a][b-1]>dp[a-1][b]) --b; auto it = addInterval(is, L, R); else --a; T r2 = it->second; return ans; if (it->first == L) is.erase(it); TernarySearch.h } else (T&)it->second = L; Description: Find the smallest i in [a, b] that maximizes f(i), assuming if (R != r2) is.emplace(R, r2); that f(a) < . . . < f(i) ≥ · · · ≥ f(b). To reverse which of the sides allows }; non-strict inequalities, change the < marked with (A) to <=, and reverse the loop at (B). To minimize f, change it to >, also at (B). Usage: int ind = ternSearch(0,n-1,[&](int i){return a[i];}); IntervalCover.h Time: O (log(b − a)) Description: Compute indices of smallest set of intervals covering another 13 lines interval. Intervals should be [inclusive, exclusive). To support [inclusive, template inclusive], change (A) to add || R.empty(). Returns empty set on failure int ternSearch(int a, int b, F f) { (or if G is empty). assert(a <= b); Time: O (N log N) 19 lines while (b - a >= 5) { int mid = (a + b) / 2; template if (f(mid) < f(mid+1)) // (A) vi cover(pair G, vector> I) { a = mid; vi S(sz(I)), R; else iota(all(S), 0); b = mid+1; sort(all(S), [&](int a, int b) { return I[a] < I[b]; }); } T cur = G.first; rep(i,a+1,b+1) if (f(a) < f(i)) a = i; // (B) int at = 0; return a; while (cur < G.second) { // (A) } pair mx = make_pair(cur, -1); UiB DivideAndConquerDP KnuthDP BumpAllocator SmallPtr BumpAllocatorSTL Unrolling SIMD 24

10.3 Dynamic programming • rep(b,0,K) rep(i,0,(1 << K)) if (i & 1 Unrolling.h 5 lines << b) D[i] += D[iˆ(1 << b)]; computes all #define F {...; ++i;} DivideAndConquerDP.h sums of subsets. int i = from; Description: Given a[i] = minlo(i)≤k= R) return; • can double performance more. If AVX is unsupported, try 128-bit operations, ”emmintrin.h” and int mid = (L + R) >> 1; of vectorized code, but causes crashes on old machines. #define SSE and MMX before including it. For aligned memory use pair best(LLONG_MAX, LO); mm malloc(size, 32) or int buf[N] alignas(32), but prefer loadu/s- rep(k, max(LO,lo(mid)), min(HI,hi(mid))) toreu. #pragma GCC optimize ("trapv") 43 lines best = min(best, make_pair(f(mid, k), k)); • kills the program on store(mid, best.second, best.first); integer overflows (but is really slow). #pragma GCC target ("avx2") // or sse4 .1 rec(L, mid, LO, best.second+1); #include "immintrin.h" rec(mid+1, R, best.second, HI); } BumpAllocator.h typedef __m256i mi; void solve(int L, int R) { rec(L, R, INT_MIN, INT_MAX); } Description: When you need to dynamically allocate many objects and #define L(x) _mm256_loadu_si256((mi*)&(x)) }; don’t care about freeing them. ”new X” otherwise has an overhead of some- thing like 0.05us + 16 per allocation. // High−level/specific methods: 8 lines // load(u)? si256, store(u)? si256, setzero si256 , mm malloc KnuthDP.h // Either globally or in a single class: // blendv (epi8 | ps |pd) (z?y: x) , movemask epi8 ( hibits of bytes ) static char buf[450 << 20]; Description: When doing DP on intervals: a[i][j] = mini128), cvtsi128 si32 (128−>lo32) f(a, c) + f(b, d) ≤ f(a, d) + f(b, c) for all a ≤ b ≤ c ≤ d. Consider also: } // permute2f128 si256(x,x,1) swaps 128−bit lanes LineContainer (ch. Data structures), monotone queues, ternary search. void operator delete(void*) {} // shuffle epi32 (x , 3∗64+2∗16+1∗4+0) == x for each lane Time: O N 2 // shuffle epi8(x, y) takes a vector instead of an imm 1 lines SmallPtr.h // Methods that work with most data types (append e . g . epi32) : Description: A 32-bit pointer that points into BumpAllocator memory. // set1, blend (i8?x:y), add, adds (sat.), mullo, sub, and/or, "BumpAllocator.h" 10 lines // andnot, abs, min, max, sign(1,x), cmp(gt | eq), unpack(lo | hi ) 10.4 Debugging tricks template struct ptr { unsigned ind; int sumi32(mi m) { union {int v[8]; mi m;} u; u.m = m; • signal(SIGSEGV, [](int) { Exit(0); }); ptr(T* p = 0) : ind(p ? unsigned((char*)p - buf) : 0) { int ret = 0; rep(i,0,8) ret += u.v[i]; return ret; } converts segfaults into Wrong Answers. Similarly one assert(ind < sizeof buf); mi zero() { return _mm256_setzero_si256(); } } mi one() { return _mm256_set1_epi32(-1); } can catch SIGABRT (assertion failures) and SIGFPE T& operator*() const { return *(T*)(buf + ind); } bool all_zero(mi m) { return _mm256_testz_si256(m, m); } (zero divisions). GLIBCXX DEBUG violations generate T* operator->() const { return &**this;} bool all_one(mi m) { return _mm256_testc_si256(m, one()); } T& operator[](int a) const { return (&**this)[a]; } explicit operator bool const return SIGABRT (or SIGSEGV on gcc 5.4.0 apparently). () { ind; } ll example_filteredDotProduct(int n, short* a, short* b) { }; int i = 0; ll r = 0; • feenableexcept(29); kills the program on NaNs mi zero = _mm256_setzero_si256(), acc = zero; while (i + 16 <= n) { (1), 0-divs (4), infinities (8) and denormals (16). BumpAllocatorSTL.h mi va = L(a[i]), vb = L(b[i]); i += 16; Description: BumpAllocator for STL containers. va = _mm256_and_si256(_mm256_cmpgt_epi16(vb, va), va); Usage: vector>> ed(N); 14 lines mi vp = _mm256_madd_epi16(va, vb); 10.5 Optimization tricks char buf[450 << 20] alignas(16); acc = _mm256_add_epi64(_mm256_unpacklo_epi32(vp, zero), size_t buf_ind = sizeof buf; _mm256_add_epi64(acc, _mm256_unpackhi_epi32(vp, zero))); 10.5.1 Bit hacks } template struct small { union {ll v[4]; mi m;} u; u.m = acc; rep(i,0,4) r += u.v[i]; • x & -x is the least bit in x. typedef T value_type; for (;i small(const U&) {} } • for (int x = m; x; ) { --x &= m; ... } T* allocate(size_t n) { loops over all subset masks of m (except m itself). buf_ind -= n * sizeof(T); buf_ind &= 0 - alignof(T); return (T*)(buf + buf_ind); • c = x&-x, r = x+c; (((rˆx) >> 2)/c) | r } is the next number after x with the same number of void deallocate(T*, size_t) {} bits set. }; UiB techniques 25

Techniques (A) Computation of binomial coefficients Knuth-Morris-Pratt Pigeon-hole principle Tries Inclusion/exclusion Rolling polynom hashes techniques.txt 159 lines Catalan number Suffix array Pick’s theorem Suffix tree Recursion Number theory Aho-Corasick Divide and conquer Integer parts Manacher’s algorithm Finding interesting points in N log N Divisibility Letter position lists Algorithm analysis Euklidean algorithm Combinatorial search Master theorem Modular arithmetic Meet in the middle Amortized time complexity Modular Brute-force with pruning Greedy algorithm * Modular inverses Best-first (A ) Scheduling * * Modular by squaring Bidirectional search Max contigous subvector sum * Chinese remainder theorem Iterative deepening DFS / A Invariants * Fermat’s small theorem Data structures Huffman encoding Euler’s theorem LCA (2ˆk-jumps in trees in general) Graph teory Phi function Pull/push-technique on trees Dynamic graphs (extra book-keeping) Frobenius number Heavy-light decomposition Breadth first search Quadratic reciprocity Centroid decomposition Depth first search Pollard-Rho Lazy propagation Normal trees / DFS trees * Miller-Rabin Self-balancing trees Dijkstra’s algoritm Hensel lifting Convex hull trick (wcipeg.com/wiki/Convex_hull_trick) MST: Prim’s algoritm Vieta root jumping Monotone queues / monotone stacks / sliding queues Bellman-Ford Game theory Sliding queue using 2 stacks Konig’s theorem and vertex cover Combinatorial games Persistent segment tree Min-cost max flow Game trees Lovasz toggle Mini-max Matrix tree theorem Nim Maximal matching, general graphs Games on graphs Hopcroft-Karp Games on graphs with loops Hall’s marriage theorem Grundy numbers Graphical sequences Bipartite games without repetition Floyd-Warshall General games without repetition Eulercykler Alpha-beta pruning Flow networks Probability theory Augumenting paths * Optimization Edmonds-Karp * Binary search Bipartite matching Ternary search Min. path cover Unimodality and convex functions Topological sorting Binary search on derivative Strongly connected components Numerical methods 2-SAT Numeric integration Cutvertices, cutedges och biconnected components Newton’s method Edge coloring Root-finding with binary/ternary search Trees * Golden section search Vertex coloring Matrices Bipartite graphs (=> trees) * Gaussian elimination 3ˆn (special case of set cover) * Exponentiation by squaring Diameter and centroid Sorting K’th shortest path sort Shortest cycle Geometry Dynamic programmering Coordinates and vectors Knapsack Cross product Coin change * Scalar product Longest common subsequence * Convex hull Longest increasing subsequence Polygon cut Number of paths in a dag Closest pair Shortest path in a dag Coordinate-compression Dynprog over intervals Quadtrees Dynprog over subsets KD-trees Dynprog over probabilities All segment-segment intersection Dynprog over trees Sweeping 3ˆn set cover Discretization (convert to events and sweep) Divide and conquer Angle sweeping Knuth optimization Line sweeping Convex hull optimizations Discrete second derivatives RMQ (sparse table a.k.a 2ˆk-jumps) Strings Bitonic cycle Longest common substring Log partitioning (loop over most restricted) Palindrome subsequences Combinatorics