kactl
kactl
Omogen Heap
Simon Lindholm, Johan Sannemo, Mårten Wiman
2024-11-24
1 Contest 1 troubleshoot.txt 52 lines
ed − bf
Pre-submit:
ax + by = e x=
2 Mathematics 1 Write a few simple test cases if sample is not enough. ad − bc
⇒
Are time limits close? If so, generate max cases. cx + dy = f af − ec
Is the memory usage fine? y=
3 Data structures 3 Could anything overflow? ad − bc
Make sure to submit the right file.
In general, given an equation Ax = b, the solution to a variable
4 Numerical 5 Wrong answer: xi is given by
Print your solution! Print debug output, as well.
det A′i
5 Number theory 8 Are you clearing all data structures between test cases? xi =
Can your algorithm handle the whole range of input? det A
Read the full problem statement again.
6 Combinatorial 10 Do you handle all corner cases correctly?
where A′i is A with the i’th column replaced by b.
Have you understood the problem correctly?
Any uninitialized variables?
2.2 Recurrences
7 Graph 11 Any overflows? If an = c1 an−1 + · · · + ck an−k , and r1 , . . . , rk are distinct roots of
Confusing N and M, i and j, etc.?
Are you sure your algorithm works?
xk − c1 xk−1 − · · · − ck , there are d1 , . . . , dk s.t.
8 Geometry 16 What special cases have you not thought of?
Are you sure the STL functions you use work as you think? an = d1 r1n + · · · + dk rkn .
9 Strings 20 Add some assertions, maybe resubmit.
Create some testcases to run your algorithm on. Non-distinct roots r become polynomial factors, e.g.
Go through the algorithm for a simple case. an = (d1 n + d2 )rn .
10 Various 22 Go through this list again.
Explain your algorithm to a teammate.
Ask the teammate to look at your code.
2.3 Trigonometry
Contest (1) Go for a small walk, e.g. to the toilet.
Is your output format correct? (including whitespace) sin(v + w) = sin v cos w + cos v sin w
Rewrite your solution from the start or let a teammate do it.
cos(v + w) = cos v cos w − sin v sin w
template.cpp 14 lines
Runtime error:
#include <bits/stdc++.h> Have you tested all corner cases locally?
using namespace std; Any uninitialized variables?
Are you reading or writing outside the range of any vector? tan v + tan w
#define rep(i, a, b) for(int i = a; i < (b); ++i) Any assertions that might fail? tan(v + w) =
#define all(x) begin(x), end(x) Any possible division by 0? (mod 0 for example) 1 − tan v tan w
#define sz(x) (int)(x).size() Any possible infinite recursion? v+w v−w
typedef long long ll; Invalidated pointers or iterators? sin v + sin w = 2 sin cos
typedef pair<int, int> pii; Are you using too much memory?
2 2
typedef vector<int> vi; Debug with resubmits (e.g. remapped signals, see Various). v+w v−w
cos v + cos w = 2 cos cos
2 2
int main() { Time limit exceeded:
cin.tie(0)->sync_with_stdio(0); Do you have any possible infinite loops? (V + W ) tan(v − w)/2 = (V − W ) tan(v + w)/2
cin.exceptions(cin.failbit); What is the complexity of your algorithm?
} Are you copying a lot of unnecessary data? (References) where V, W are lengths of sides opposite angles v, w.
How big is the input and output? (consider scanf)
Avoid vector, map. (use arrays/unordered_map) a cos x + b sin x = r cos(x − ϕ)
.bashrc 3 lines What do your teammates think about your algorithm?
alias c=’g++ -Wall -Wconversion -Wfatal-errors -g -std=c++17 \
a sin x + b cos x = r sin(x + ϕ)
-fsanitize=undefined,address’ Memory limit exceeded: √
xmodmap -e ’clear lock’ -e ’keycode 66=less greater’ #caps = <> What is the max amount of memory your algorithm should need? where r = a2 + b2 , ϕ = atan2(b, a).
Are you clearing all data structures between test cases?
2.4 Geometry
.vimrc 6 lines
2.4.1 Triangles
set cin aw ai is ts=4 sw=4 tm=50 nu noeb bg=dark ru cul
sy on | im jk <esc> | im kj <esc> | no ; :
Mathematics (2) Side lengths: a, b, c
" Select region and then type :Hash to hash your selection. a+b+c
Semiperimeter: p =
" Useful for verifying that there aren’t mistypes.
ca Hash w !cpp -dD -P -fpreprocessed \| tr -d ’[:space:]’ \
2.1 Equations p 2
Area: A = p(p − a)(p − b)(p − c)
\| md5sum \| cut -c-6 √ abc
2 −b ± b2 − 4ac Circumradius: R =
ax + bx + c = 0 ⇒ x = 4A
hash.sh 3 lines
2a A
Inradius: r =
# Hashes a file, ignoring all whitespace and comments. Use for p
# verifying that code was correctly typed. Length √of median (divides triangle into two equal-area triangles):
cpp -dD -P -fpreprocessed | tr -d ’[:space:]’| md5sum |cut -c-6
The extremum is given by x = −b/2a. ma = 12 2b2 + 2c2 − a2
KTH template .bashrc .vimrc hash troubleshoot 2
Length
v of "bisector (divides angles in two): 2.6 Sums First success distribution
u 2 # a a+1 b cb+1 − ca
The number of trials needed to get the first success in
u a c +c + ··· + c = , c ̸= 1
sa = tbc 1 − c−1 independent yes/no experiments, each which yields success with
b+c
n(n + 1) probability p is Fs(p), 0 ≤ p ≤ 1.
sin α sin β sin γ 1 1 + 2 + 3 + ··· + n =
Law of sines: = = = 2
a b c 2R p(k) = p(1 − p)k−1 , k = 1, 2, . . .
Law of cosines: a2 = b2 + c2 − 2bc cos α 2 2 2 2 n(2n + 1)(n + 1)
1 + 2 + 3 + ··· + n =
α+β 6
a+b tan 1 2 1−p
Law of tangents: = 2 3 3 3 3 n2 (n + 1)2 µ= ,σ =
a−b α−β 1 + 2 + 3 + ··· + n = p p2
tan 4
2 n(n + 1)(2n + 1)(3n2 + 3n − 1)
2.4.2 Quadrilaterals 4 4 4 4
1 + 2 + 3 + ··· + n = Poisson distribution
With side lengths a, b, c, d, diagonals e, f , diagonals angle θ, area 30
The number of events occurring in a fixed period of time t if these
A and magic flux F = b2 + d2 − a2 − c2 : events occur with a known average rate κ and independently of
2.7 Series the time since the last event is Po(λ), λ = tκ.
x2 x3
ex = 1 + x +
p
4A = 2ef · sin θ = F tan θ = 4e2 f 2 − F 2 + + . . . , (−∞ < x < ∞) λk
2! 3! p(k) = e−λ , k = 0, 1, 2, . . .
x 2
x 3
x4 k!
ln(1 + x) = x − + − + . . . , (−1 < x ≤ 1)
For cyclic quadrilateralspthe sum of opposite angles is 180◦ , 2 3 4
ef = ac + bd, and A = (p − a)(p − b)(p − c)(p − d). √ x x2 2x3 5x4 µ = λ, σ 2 = λ
1+x=1+ − + − + . . . , (−1 ≤ x ≤ 1)
2.4.3 Spherical coordinates 2 8 32 128
3 5 7 2.8.2 Continuous distributions
x x x
z sin x = x − + − + . . . , (−∞ < x < ∞) Uniform distribution
3! 5! 7!
2 4 6
r cos x = 1 −
x
+
x
−
x
+ . . . , (−∞ < x < ∞)
If the probability density function is constant between a and b
y 2! 4! 6! and 0 elsewhere it is U(a, b), a < b.
2.8 Probability theory 1
a<x<b
x Let X be a discrete random variable with probability pX (x) of f (x) = b−a
0 otherwise
assuming theP value x. It will then have an expected value (mean)
µ = E(X) = x xpX (x) and variance
(b − a)2
p
σ 2 = V (X) = E(X 2 ) − (E(X))2 = x (x − E(X))2 pX (x) where σ a+b 2
2 + y2 + z2
P
x = r sin θ cos ϕ r = xp µ= ,σ =
y = r sin θ sin ϕ θ = acos(z/ x2 + y 2 + z 2 ) is the standard deviation. If X is instead continuous it will have 2 12
z = r cos θ ϕ = atan2(y, x) a probability density function fX (x) and the sums above will
Exponential distribution
instead be integrals with pX (x) replaced by fX (x).
The time between events in a Poisson process is
2.5 Derivatives/Integrals Expectation is linear: Exp(λ), λ > 0.
E(aX + bY ) = aE(X) + bE(Y ) λe−λx x ≥ 0
f (x) =
d 1 d 1 For independent X and Y , 0 x<0
arcsin x = √ arccos x = − √
dx 1 − x2 dx 1 − x2 V (aX + bY ) = a2 V (X) + b2 V (Y ). 1 2 1
d d 1 µ= ,σ = 2
tan x = 1 + tan2 x arctan x = λ λ
dx dx 1 + x2 2.8.1 Discrete distributions
Z
ln | cos ax|
Z
sin ax − ax cos ax Binomial distribution Normal distribution
tan ax = − x sin ax =
a a2 Most real random values with mean µ and variance σ 2 are well
√ ax The number of successes in n independent yes/no experiments,
described by N (µ, σ 2 ), σ > 0.
Z Z
−x2 π e
e = erf(x) xeax dx = 2 (ax − 1) each which yields success with probability p is
2 a Bin(n, p), n = 1, 2, . . . , 0 ≤ p ≤ 1.
1 (x−µ)2
−
! f (x) = √ e 2σ2
n k 2πσ 2
Integration by parts: p(k) = p (1 − p)n−k
k
If X1 ∼ N (µ1 , σ12 ) and X2 ∼ N (µ2 , σ22 ) then
Z b Z b µ = np, σ 2 = np(1 − p)
f (x)g(x)dx = [F (x)g(x)]ba − F (x)g ′ (x)dx Bin(n, p) is approximately Po(np) for small p. aX1 + bX2 + c ∼ N (µ1 + µ2 + c, a2 σ12 + b2 σ22 )
a a
KTH OrderStatisticTree HashMap SegmentTree LazySegmentTree UnionFindRollback SubMatrix 3
2.9 Markov chains Description: Hash map with mostly the same API as unordered map, but val = max(l->val, r->val);
∼3x faster. Uses 1.5x memory. Initial capacity must be a power of 2 (if }
A Markov chain is a discrete random process with the property provided). }
d77092, 7 lines
that the next state depends only on the current state. Let void add(int L, int R, int x) {
#include <bits/extc++.h> if (R <= lo || hi <= L) return;
X1 , X2 , . . . be a sequence of random variables generated by the // To use most b i t s rather than j u s t the lowest ones : if (L <= lo && hi <= R) {
Markov process. Then there is a transition matrix P = (pij ), struct chash { // large odd number for C if (mset != inf) mset += x;
with pij = Pr(Xn = i|Xn−1 = j), and p(n) = Pn p(0) is the const uint64_t C = ll(4e18 * acos(0)) | 71; else madd += x;
(n)
ll operator()(ll x) const { return __builtin_bswap64(x*C); } val += x;
probability distribution for Xn (i.e., pi = Pr(Xn = i)), where }; }
(0) __gnu_pbds::gp_hash_table<ll,int,chash> h({},{},{},{},{1<<16});
p is the initial distribution. else {
push(), l->add(L, R, x), r->add(L, R, x);
π is a stationary distribution if π = πP. If the Markov chain is SegmentTree.h val = max(l->val, r->val);
Description: Zero-indexed max-tree. Bounds are inclusive to the left and }
irreducible (it is possible to get to any state from any state), then exclusive to the right. Can be changed by modifying T, f and unit. }
πi = E(T1 i ) where E(Ti ) is the expected time between two visits in Time: O (log N ) 0f4bdb, 19 lines
void push() {
if (!l) {
state i. πj /πi is the expected number of visits in state j between struct Tree { int mid = lo + (hi - lo)/2;
two visits in state i. typedef int T; l = new Node(lo, mid); r = new Node(mid, hi);
static constexpr T unit = INT_MIN; }
T f(T a, T b) { return max(a, b); } // (any associative fn ) if (mset != inf)
For a connected, undirected and non-bipartite graph, where the vector<T> s; int n; l->set(lo,hi,mset), r->set(lo,hi,mset), mset = inf;
transition probability is uniform among all neighbors, πi is Tree(int n = 0, T def = unit) : s(2*n, def), n(n) {} else if (madd)
proportional to node i’s degree. void update(int pos, T val) { l->add(lo,hi,madd), r->add(lo,hi,madd), madd = 0;
for (s[pos += n] = val; pos /= 2;) }
s[pos] = f(s[pos * 2], s[pos * 2 + 1]); };
A Markov chain is ergodic if the asymptotic distribution is }
independent of the initial distribution. A finite Markov chain is T query(int b, int e) { // query [ b , e)
ergodic iff it is irreducible and aperiodic (i.e., the gcd of cycle T ra = unit, rb = unit; UnionFindRollback.h
for (b += n, e += n; b < e; b /= 2, e /= 2) { Description: Disjoint-set data structure with undo. If undo is not needed,
lengths is 1). limk→∞ Pk = 1π. if (b % 2) ra = f(ra, s[b++]); skip st, time() and rollback().
if (e % 2) rb = f(s[--e], rb); Usage: int t = uf.time(); ...; uf.rollback(t);
A Markov chain is an A-chain if the states can be partitioned } Time: O (log(N )) de4ad0, 21 lines
return f(ra, rb);
into two sets A and G, such that all states in A are absorbing }
struct RollbackUF {
(pii = 1), and all states in G leads to an absorbing state in A. vi e; vector<pii> st;
};
RollbackUF(int n) : e(n, -1) {}
The probability for absorption in state i ∈ A, when the initial int size(int x) { return -e[find(x)]; }
LazySegmentTree.h
P
state is j, is aij = pij + k∈G aik pkj . The expected
P time until
int find(int x) { return e[x] < 0 ? x : find(e[x]); }
absorption, when the initial state is i, is ti = 1 + k∈G pki tk . Description: Segment tree with ability to add or set values of large inter- int time() { return sz(st); }
vals, and compute max of intervals. Can be changed to other things. Use void rollback(int t) {
with a bump allocator for better performance, and SmallPtr or implicit in- for (int i = time(); i --> t;)
dices to save memory. e[st[i].first] = st[i].second;
Usage: Node* tr = new Node(v, 0, sz(v)); st.resize(t);
Data structures (3) Time: O (log N ). }
"../various/BumpAllocator.h" 34ecf5, 50 lines bool join(int a, int b) {
OrderStatisticTree.h const int inf = 1e9; a = find(a), b = find(b);
Description: A set (not multiset!) with support for finding the n’th ele- struct Node { if (a == b) return false;
ment, and finding the index of an element. To get a map, change null type. Node *l = 0, *r = 0; if (e[a] > e[b]) swap(a, b);
Time: O (log N ) int lo, hi, mset = inf, madd = 0, val = -inf; st.push_back({a, e[a]});
782797, 16 lines
Node(int lo,int hi):lo(lo),hi(hi){} // Large interval of =in f st.push_back({b, e[b]});
#include <bits/extc++.h> Node(vi& v, int lo, int hi) : lo(lo), hi(hi) { e[a] += e[b]; e[b] = a;
using namespace __gnu_pbds; if (lo + 1 < hi) { return true;
int mid = lo + (hi - lo)/2; }
template<class T> l = new Node(v, lo, mid); r = new Node(v, mid, hi); };
using Tree = tree<T, null_type, less<T>, rb_tree_tag, val = max(l->val, r->val);
tree_order_statistics_node_update>; }
else val = v[lo];
SubMatrix.h
void example() { Description: Calculate submatrix sums quickly, given upper-left and lower-
} right corners (half-open).
Tree<int> t, t2; t.insert(8); int query(int L, int R) {
auto it = t.insert(10).first; Usage: SubMatrix<int> m(matrix);
if (R <= lo || hi <= L) return -inf; m.sum(0, 0, 2, 2); // top left 4 elements
assert(it == t.lower_bound(9)); if (L <= lo && hi <= R) return val; Time: O N 2 + Q
assert(t.order_of_key(10) == 1); push(); c59ada, 13 lines
assert(t.order_of_key(11) == 2); return max(l->query(L, R), r->query(L, R)); template<class T>
assert(*t.find_by_order(0) == 8); } struct SubMatrix {
t.join(t2); // assuming T < T2 or T > T2, merge t2 into t void set(int L, int R, int x) { vector<vector<T>> p;
} if (R <= lo || hi <= L) return; SubMatrix(vector<vector<T>>& v) {
if (L <= lo && hi <= R) mset = val = x, madd = 0; int R = sz(v), C = sz(v[0]);
HashMap.h else { p.assign(R+1, vector<T>(C+1));
push(), l->set(L, R, x), r->set(L, R, x); rep(r,0,R) rep(c,0,C)
KTH Matrix LineContainer Treap FenwickTree FenwickTree2d RMQ 4
p[r+1][c+1] = v[r][c] + p[r][c+1] + p[r+1][c] - p[r][c]; isect(x, erase(y)); FenwickTree.h
} } Description: Computes partial sums a[0] + a[1] + ... + a[pos - 1], and
T sum(int u, int l, int d, int r) { ll query(ll x) { updates single elements a[i], taking the difference between the old and new
return p[d][r] - p[d][l] - p[u][r] + p[u][l]; assert(!empty()); value.
} auto l = *lower_bound(x); Time: Both operations are O (log N ). e62fac, 22 lines
}; return l.k * x + l.m;
} struct FT {
}; vector<ll> s;
Matrix.h FT(int n) : s(n) {}
Description: Basic operations on square matrices. void update(int pos, ll dif) { // a [ pos ] += d i f
Usage: Matrix<int, 3> A; Treap.h for (; pos < sz(s); pos |= pos + 1) s[pos] += dif;
A.d = {{{{1,2,3}}, {{4,5,6}}, {{7,8,9}}}}; Description: A short self-balancing tree. It acts as a sequential container }
vector<int> vec = {1,2,3}; with log-time splits/joins, and is easy to augment with additional data. ll query(int pos) { // sum of values in [0 , pos)
vec = (AˆN) * vec; Time: O (log N ) 9556fc, 55 lines ll res = 0;
c43c7d, 26 lines
struct Node { for (; pos > 0; pos &= pos - 1) res += s[pos-1];
template<class T, int N> struct Matrix { return res;
typedef Matrix M; Node *l = 0, *r = 0;
int val, y, c = 1; }
array<array<T, N>, N> d{}; int lower_bound(ll sum) {// min pos s t sum of [0 , pos ] >= sum
Node(int val) : val(val), y(rand()) {}
M operator*(const M& m) const {
void recalc(); // Returns n i f no sum i s >= sum, or =1 i f empty sum i s .
M a; if (sum <= 0) return -1;
rep(i,0,N) rep(j,0,N) };
int pos = 0;
rep(k,0,N) a.d[i][j] += d[i][k]*m.d[k][j]; for (int pw = 1 << 25; pw; pw >>= 1) {
return a; int cnt(Node* n) { return n ? n->c : 0; }
void Node::recalc() { c = cnt(l) + cnt(r) + 1; } if (pos + pw <= sz(s) && s[pos + pw-1] < sum)
} pos += pw, sum -= s[pos-1];
vector<T> operator*(const vector<T>& vec) const { }
vector<T> ret(N); template<class F> void each(Node* n, F f) {
if (n) { each(n->l, f); f(n->val); each(n->r, f); } return pos;
rep(i,0,N) rep(j,0,N) ret[i] += d[i][j] * vec[j]; }
return ret; }
};
}
M operator^(ll p) const { pair<Node*, Node*> split(Node* n, int k) {
assert(p >= 0); if (!n) return {}; FenwickTree2d.h
M a, b(*this); if (cnt(n->l) >= k) { // ”n=>val >= k” for lower bound(k) Description: Computes sums a[i,j] for all i<I, j<J, and increases single ele-
rep(i,0,N) a.d[i][i] = 1; auto pa = split(n->l, k); ments a[i,j]. Requires that the elements to be updated are known in advance
while (p) { n->l = pa.second; (call fakeUpdate() before init()).
if (p&1) a = a*b; n->recalc(); Time: O log2 N . (Use persistent segment trees for O (log N ).)
b = b*b; return {pa.first, n}; "FenwickTree.h" 157f07, 22 lines
p >>= 1; } else { struct FT2 {
} auto pa = split(n->r, k - cnt(n->l) - 1); // and j u s t ”k” vector<vi> ys; vector<FT> ft;
return a; n->r = pa.first; FT2(int limx) : ys(limx) {}
} n->recalc(); void fakeUpdate(int x, int y) {
}; return {n, pa.second}; for (; x < sz(ys); x |= x + 1) ys[x].push_back(y);
} }
} void init() {
LineContainer.h for (vi& v : ys) sort(all(v)), ft.emplace_back(sz(v));
Description: Container where you can add lines of the form kx+m, and Node* merge(Node* l, Node* r) { }
query maximum values at points x. Useful for dynamic programming (“con- if (!l) return r; int ind(int x, int y) {
vex hull trick”). if (!r) return l; return (int)(lower_bound(all(ys[x]), y) - ys[x].begin()); }
Time: O (log N ) if (l->y > r->y) {
8ec1c7, 30 lines void update(int x, int y, ll dif) {
l->r = merge(l->r, r); for (; x < sz(ys); x |= x + 1)
struct Line {
l->recalc(); ft[x].update(ind(x, y), dif);
mutable ll k, m, p;
return l; }
bool operator<(const Line& o) const { return k < o.k; }
} else { ll query(int x, int y) {
bool operator<(ll x) const { return p < x; }
r->l = merge(l, r->l); ll sum = 0;
};
r->recalc(); for (; x; x &= x - 1)
return r; sum += ft[x-1].query(ind(x-1, y));
struct LineContainer : multiset<Line, less<>> {
} return sum;
// ( for doubles , use i nf = 1/.0 , div (a , b) = a/b)
} }
static const ll inf = LLONG_MAX;
ll div(ll a, ll b) { // floored division };
Node* ins(Node* t, Node* n, int pos) {
return a / b - ((a ^ b) < 0 && a % b); }
auto pa = split(t, pos);
bool isect(iterator x, iterator y) { RMQ.h
return merge(merge(pa.first, n), pa.second);
if (y == end()) return x->p = inf, 0; Description: Range Minimum Queries on an array. Returns min(V[a], V[a
}
if (x->k == y->k) x->p = x->m > y->m ? inf : -inf; + 1], ... V[b - 1]) in constant time.
else x->p = div(y->m - x->m, x->k - y->k); Usage: RMQ rmq(values);
// Example application : move the range [ l , r ) to index k
return x->p >= y->p; rmq.query(inclusive, exclusive);
void move(Node*& t, int l, int r, int k) {
} Time: O (|V | log |V | + Q)
Node *a, *b, *c; 510c32, 16 lines
void add(ll k, ll m) {
tie(a,b) = split(t, l); tie(b,c) = split(b, r - l);
auto z = insert({k, m, 0}), y = z++, x = y; template<class T>
if (k <= l) t = merge(ins(a, b, k), c);
while (isect(y, z)) z = erase(z); struct RMQ {
else t = merge(a, ins(c, b, k - r));
if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); vector<vector<T>> jmp;
}
while ((y = x) != begin() && (--x)->p >= y->p) RMQ(const vector<T>& V) : jmp(1, V) {
KTH MoQueries Polynomial PolyRoots PolyInterpolate BerlekampMassey LinearRecurrence 5
for (int pw = 1, k = 1; pw * 2 <= sz(V); pw *= 2, ++k) {
jmp.emplace_back(sz(V) - pw * 2 + 1);
Numerical (4) }
return res;
rep(j,0,sz(jmp[k])) }
jmp[k][j] = min(jmp[k - 1][j], jmp[k - 1][j + pw]); 4.1 Polynomials and recurrences
} Polynomial.h c9b7b0, 17 lines
}
T query(int a, int b) { struct Poly { BerlekampMassey.h
vector<double> a; Description: Recovers any n-order linear recurrence relation from the first
assert(a < b); // or return i n f i f a == b
double operator()(double x) const { 2n terms of the recurrence. Useful for guessing linear recurrences after brute-
int dep = 31 - __builtin_clz(b - a);
double val = 0; forcing the first terms. Should work on any field, but numerical stability for
return min(jmp[dep][a], jmp[dep][b - (1 << dep)]);
for (int i = sz(a); i--;) (val *= x) += a[i]; floats is not guaranteed. Output will have size ≤ n.
}
return val; Usage: berlekampMassey({0, 1, 1, 3, 5, 11}) // {1, 2}
};
Time: O N 2
}
"../number-theory/ModPow.h" 96548b, 20 lines
void diff() {
MoQueries.h rep(i,1,sz(a)) a[i-1] = i*a[i]; vector<ll> berlekampMassey(vector<ll> s) {
Description: Answer interval or tree path queries by finding an approxi- int n = sz(s), L = 0, m = 0;
a.pop_back();
mate TSP through the queries, and moving from one query to the next by vector<ll> C(n), B(n), T;
}
adding/removing points at the ends. If values are on tree edges, change step C[0] = B[0] = 1;
void divroot(double x0) {
to add/remove
√ the
edge (a, c) and remove the initial add call (but keep in). double b = a.back(), c; a.back() = 0;
Time: O N Q ll b = 1;
a12ef4, 49 lines for(int i=sz(a)-1; i--;) c = a[i], a[i] = a[i+1]*x0+b, b=c;
void add(int ind, int end) { ... } // add a [ ind ] (end = 0 or 1) a.pop_back(); rep(i,0,n) { ++m;
void del(int ind, int end) { ... } // remove a [ ind ] } ll d = s[i] % mod;
int calc() { ... } // compute current answer }; rep(j,1,L+1) d = (d + C[j] * s[i - j]) % mod;
if (!d) continue;
T = C; ll coef = d * modpow(b, mod-2) % mod;
vi mo(vector<pii> Q) { PolyRoots.h rep(j,m,n) C[j] = (C[j] - coef * B[j - m]) % mod;
int L = 0, R = 0, blk = 350; // ∼N/sqrt (Q) Description: Finds the real roots to a polynomial.
vi s(sz(Q)), res = s; if (2 * L > i) continue;
Usage: polyRoots({{2,-3,1}},-1e9,1e9) // solve xˆ2-3x+2 = 0
L = i + 1 - L; B = T; b = d; m = 0;
Time: O n2 log(1/ϵ)
#define K(x) pii(x.first/blk, x.second ^ -(x.first/blk & 1))
iota(all(s), 0); }
"Polynomial.h" b00bfe, 23 lines
sort(all(s), [&](int s, int t){ return K(Q[s]) < K(Q[t]); });
vector<double> polyRoots(Poly p, double xmin, double xmax) { C.resize(L + 1); C.erase(C.begin());
for (int qi : s) {
if (sz(p.a) == 2) { return {-p.a[0]/p.a[1]}; } for (ll& x : C) x = (mod - x) % mod;
pii q = Q[qi];
vector<double> ret; return C;
while (L > q.first) add(--L, 0);
Poly der = p; }
while (R < q.second) add(R++, 1);
der.diff();
while (L < q.first) del(L++, 0);
auto dr = polyRoots(der, xmin, xmax);
while (R > q.second) del(--R, 1);
dr.push_back(xmin-1);
res[qi] = calc();
dr.push_back(xmax+1); LinearRecurrence.h
} Description: Generates the k’th term of an n-order linear recurrence
sort(all(dr));
return res; P
rep(i,0,sz(dr)-1) { S[i] = j S[i − j − 1]tr[j], given S[0 . . . ≥ n − 1] and tr[0 . . . n − 1]. Faster
} than matrix multiplication. Useful together with Berlekamp–Massey.
double l = dr[i], h = dr[i+1];
bool sign = p(l) > 0; Usage: linearRec({0, 1}, {1, 1}, k) // k’th Fibonacci number
vi moTree(vector<array<int, 2>> Q, vector<vi>& ed, int root=0){ Time: O n2 log k
if (sign ^ (p(h) > 0)) { f4e444, 26 lines
int N = sz(ed), pos[2] = {}, blk = 350; // ∼N/sqrt (Q)
rep(it,0,60) { // while (h = l > 1e=8)
vi s(sz(Q)), res = s, I(N), L(N), R(N), in(N), par(N); typedef vector<ll> Poly;
double m = (l + h) / 2, f = p(m);
add(0, 0), in[0] = 1; ll linearRec(Poly S, Poly tr, ll k) {
if ((f <= 0) ^ sign) l = m;
auto dfs = [&](int x, int p, int dep, auto& f) -> void { int n = sz(tr);
else h = m;
par[x] = p;
}
L[x] = N; auto combine = [&](Poly a, Poly b) {
ret.push_back((l + h) / 2);
if (dep) I[x] = N++; Poly res(n * 2 + 1);
}
for (int y : ed[x]) if (y != p) f(y, x, !dep, f); rep(i,0,n+1) rep(j,0,n+1)
}
if (!dep) I[x] = N++; res[i + j] = (res[i + j] + a[i] * b[j]) % mod;
return ret;
R[x] = N; for (int i = 2 * n; i > n; --i) rep(j,0,n)
}
}; res[i - 1 - j] = (res[i - 1 - j] + res[i] * tr[j]) % mod;
dfs(root, -1, 0, dfs); res.resize(n + 1);
#define K(x) pii(I[x[0]] / blk, I[x[1]] ^ -(I[x[0]] / blk & 1)) PolyInterpolate.h return res;
iota(all(s), 0); Description: Given n points (x[i], y[i]), computes an n-1-degree polynomial };
sort(all(s), [&](int s, int t){ return K(Q[s]) < K(Q[t]); }); p that passes through them: p(x) = a[0] ∗ x0 + ... + a[n − 1] ∗ xn−1 . For
for (int qi : s) rep(end,0,2) { numerical precision, pick x[k] = c ∗ cos(k/(n − 1) ∗ π), k = 0 . . . n − 1. Poly pol(n + 1), e(pol);
Time: O n2
int &a = pos[end], b = Q[qi][end], i = 0; 08bf48, 13 lines pol[0] = e[1] = 1;
#define step(c) { if (in[c]) { del(a, end); in[a] = 0; } \
typedef vector<double> vd;
else { add(c, end); in[c] = 1; } a = c; } for (++k; k; k /= 2) {
vd interpolate(vd x, vd y, int n) {
while (!(L[b] <= L[a] && R[a] <= R[b])) if (k % 2) pol = combine(pol, e);
vd res(n), temp(n);
I[i++] = b, b = par[b]; e = combine(e, e);
rep(k,0,n-1) rep(i,k+1,n)
while (a != b) step(par[a]); }
y[i] = (y[i] - y[k]) / (x[i] - x[k]);
while (i--) step(I[i]);
double last = 0; temp[0] = 1;
if (end) res[qi] = calc(); ll res = 0;
rep(k,0,n) rep(i,0,n) {
} rep(i,0,n) res = (res + pol[i + 1] * S[i]) % mod;
res[i] += y[k] * temp[i];
return res; return res;
swap(last, temp[i]);
} }
temp[i] -= last * x[k];
KTH GoldenSectionSearch HillClimbing Integrate IntegrateAdaptive Simplex Determinant IntDeterminant 6
4.2 Optimization d rec(F& f, d a, d b, d eps, d S) { < MP(D[r][n+1] / D[r][s], B[r])) r = i;
d c = (a + b) / 2; }
GoldenSectionSearch.h d S1 = S(a, c), S2 = S(c, b), T = S1 + S2; if (r == -1) return false;
Description: Finds the argument minimizing the function f in the interval
if (abs(T - S) <= 15 * eps || b - a < 1e-10) pivot(r, s);
[a, b] assuming f is unimodal on the interval, i.e. has only one local mini-
return T + (T - S) / 15; }
mum and no local maximum. The maximum error in the result is eps. Works
return rec(f, a, c, eps / 2, S1) + rec(f, c, b, eps / 2, S2); }
equally well for maximization with a small change in the code. See Ternary-
}
Search.h in the Various chapter for a discrete version.
template<class F> T solve(vd &x) {
Usage: double func(double x) { return 4+x+.3*x*x; }
d quad(d a, d b, F f, d eps = 1e-8) { int r = 0;
double xmin = gss(-1000,1000,func);
return rec(f, a, b, eps, S(a, b)); rep(i,1,m) if (D[i][n+1] < D[r][n+1]) r = i;
Time: O (log((b − a)/ϵ)) 31d45b, 14 lines } if (D[r][n+1] < -eps) {
double gss(double a, double b, double (*f)(double)) { pivot(r, n);
double r = (sqrt(5)-1)/2, eps = 1e-7; if (!simplex(2) || D[m+1][n+1] < -eps) return -inf;
double x1 = b - r*(b-a), x2 = a + r*(b-a); Simplex.h rep(i,0,m) if (B[i] == -1) {
double f1 = f(x1), f2 = f(x2); Description: Solves a general linear maximization problem: maximize cT x int s = 0;
while (b-a > eps) subject to Ax ≤ b, x ≥ 0. Returns -inf if there is no solution, inf if there rep(j,1,n+1) ltj(D[i]);
if (f1 < f2) { //change to > to find maximum are arbitrarily good solutions, or the maximum value of cT x otherwise. The pivot(i, s);
b = x2; x2 = x1; f2 = f1; input vector is set to an optimal x (or in the unbounded case, an arbitrary }
x1 = b - r*(b-a); f1 = f(x1); solution fulfilling the constraints). Numerical stability is not guaranteed. For }
} else { better performance, define variables such that x = 0 is viable. bool ok = simplex(1); x = vd(n);
a = x1; x1 = x2; f1 = f2; Usage: vvd A = {{1,-1}, {-1,1}, {-1,-2}}; rep(i,0,m) if (B[i] < n) x[B[i]] = D[i][n+1];
x2 = a + r*(b-a); f2 = f(x2); vd b = {1,1,-4}, c = {-1,-1}, x; return ok ? D[m][n+1] : inf;
} T val = LPSolver(A, b, c).solve(x); }
return a; Time: O (N M ∗ #pivots), where a pivot may be e.g. an edge relaxation. };
} O (2n ) in the general case. aa8530, 68 lines
cific nice primes of the form 2a b + 1, where the convolution result has size ull sumsq(ull to) { return to / 2 * ((to-1) | 1); }
at mostP 2a . For arbitrary modulo, see FFTMod. conv(a, b) = c, where
c[x] = a[i]b[x − i]. For manual convolution: NTT the inputs, multiply
5.1 Modular arithmetic
ull divsum(ull to, ull c, ull k, ull m) {
pointwise, divide by n, reverse(start+1, end), NTT back. Inputs must be in ModularArithmetic.h ull res = k / m * sumsq(to) + c / m * to;
[0, mod). Description: Operators for modular arithmetic. You need to set mod to k %= m; c %= m;
Time: O (N log N ) some number first and then you can use the structure. if (!k) return res;
"../number-theory/ModPow.h" ced03d, 35 lines "euclid.h" 35bfea, 18 lines ull to2 = (to * k + c) / m;
const ll mod = (119 << 23) + 1, root = 62; // = 998244353 const ll mod = 17; // change to something e l s e return res + (to - 1) * to2 - divsum(to2, m-1 - c, m, k);
// For p < 2^30 there i s also e . g . 5 << 25, 7 << 26, 479 << 21 struct Mod { }
KTH ModMulLL ModSqrt FastEratosthenes MillerRabin Factor euclid CRT phiFunction ContinuedFractions 9
for (int L = 1; L <= R; L += S) { CRT.h
ll modsum(ull to, ll c, ll k, ll m) { array<bool, S> block{}; Description: Chinese Remainder Theorem.
c = ((c % m) + m) % m; for (auto &[p, idx] : cp) crt(a, m, b, n) computes x such that x ≡ a (mod m), x ≡ b (mod n). If
k = ((k % m) + m) % m; for (int i=idx; i < S+L; idx = (i+=p)) block[i-L] = 1; |a| < m and |b| < n, x will obey 0 ≤ x < lcm(m, n). Assumes mn < 262 .
return to * c + k * sumsq(to) - m * divsum(to, c, k, m); rep(i,0,min(S, R - L)) Time: log(n)
} if (!block[i]) pr.push_back((L + i) * 2 + 1); "euclid.h" 04d93a, 7 lines
} ll crt(ll a, ll m, ll b, ll n) {
for (int i : pr) isPrime[i] = 1;
ModMulLL.h return pr;
if (n > m) swap(a, b), swap(m, n);
Description: Calculate a·b mod c (or ab mod c) for 0 ≤ a, b ≤ c ≤ 7.2·1018 . ll x, y, g = euclid(m, n, x, y);
} assert((a - b) % g == 0); // e l s e no solution
Time: O (1) for modmul, O (log b) for modpow bbbd8f, 11 lines
x = (b - a) % n * x % n / g * m + a;
typedef unsigned long long ull; return x < 0 ? x + m*n/g : x;
ull modmul(ull a, ull b, ull M) { MillerRabin.h }
ll ret = a * b - M * ull(1.L / M * a * b); Description: Deterministic Miller-Rabin primality test. Guaranteed to
return ret + M * (ret < 0) - M * (ret >= (ll)M); work for numbers up to 7 · 1018 ; for larger numbers, use Python and ex-
} tend A randomly. 5.3.1 Bézout’s identity
ull modpow(ull b, ull e, ull mod) { Time: 7 times the complexity of ab mod c. For a ̸=, b ̸= 0, then d = gcd(a, b) is the smallest positive integer
"ModMulLL.h" 60dcd1, 12 lines
ull ans = 1; for which there are integer solutions to
for (; e; b = modmul(b, b, mod), e /= 2) bool isPrime(ull n) {
if (e & 1) ans = modmul(ans, b, mod); if (n < 2 || n % 6 % 4 != 1) return (n | 1) == 3;
return ans; ull A[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022}, ax + by = d
} s = __builtin_ctzll(n-1), d = n >> s;
for (ull a : A) { // ^ count t r a i l i n g zeroes If (x, y) is one solution, then all solutions are given by
ull p = modpow(a%n, d, n), i = s;
ModSqrt.h while (p != 1 && p != n - 1 && a % n && i--)
Description: Tonelli-Shanks algorithm for modular square roots. Finds x kb ka
s.t. x2 = a (mod p) (−x gives the other solution).
p = modmul(p, p, n); x+ ,y − , k∈Z
if (p != n-1 && i != s) return 0; gcd(a, b) gcd(a, b)
Time: O log2 p worst case, O (log p) for most p
}
"ModPow.h" 19a793, 24 lines
return 1;
ll sqrt(ll a, ll p) { } phiFunction.h
a %= p; if (a < 0) a += p; Description: Euler’s ϕ function is defined as ϕ(n) := # of positive integers
if (a == 0) return 0; ≤ n that are coprime with n. ϕ(1) = 1, p prime ⇒ ϕ(pk ) = (p − 1)pk−1 ,
assert(modpow(a, (p-1)/2, p) == 1); // e l s e no solution Factor.h k
m, n coprime ⇒ ϕ(mn) = ϕ(m)ϕ(n). If n = p1 1 p2 2 ...pk
k r then ϕ(n) =
if (p % 4 == 3) return modpow(a, (p+1)/4, p); r
Description: Pollard-rho randomized factorization algorithm. Returns k1 −1 kr −1
// a^(n+3)/8 or 2^(n+3)/8 * 2^(n=1)/4 works i f p % 8 == 5
Q
(p1 − 1)p1 ...(pr − 1)pr . ϕ(n) = n · p|n (1 − 1/p).
ofa number, in arbitrary order (e.g. 2299 -> {11, 19, 11}).
prime factors P P
ll s = p - 1, n = 2; Time: O n1/4 , less for numbers with small factors. d|n ϕ(d) = n, 1≤k≤n,gcd(k,n)=1 k = nϕ(n)/2, n > 1
int r = 0, m; Euler’s thm: a, n coprime ⇒ aϕ(n) ≡ 1 (mod n).
"ModMulLL.h", "MillerRabin.h" d8d98d, 18 lines
while (s % 2 == 0)
ull pollard(ull n) { Fermat’s little thm: p prime ⇒ ap−1 ≡ 1 (mod p) ∀a.
++r, s /= 2; cf7d6d, 8 lines
while (modpow(n, (p - 1) / 2, p) != p - 1) ++n; ull x = 0, y = 0, t = 30, prd = 2, i = 1, q; const int LIM = 5000000;
ll x = modpow(a, (s + 1) / 2, p); auto f = [&](ull x) { return modmul(x, x, n) + i; }; int phi[LIM];
ll b = modpow(a, s, p), g = modpow(n, s, p); while (t++ % 40 || __gcd(prd, n) == 1) {
for (;; r = m) { if (x == y) x = ++i, y = f(x); void calculatePhi() {
ll t = b; if ((q = modmul(prd, max(x,y) - min(x,y), n))) prd = q; rep(i,0,LIM) phi[i] = i&1 ? i : i/2;
for (m = 0; m < r && t != 1; ++m) x = f(x), y = f(f(y)); for (int i = 3; i < LIM; i += 2) if(phi[i] == i)
t = t * t % p; } for (int j = i; j < LIM; j += i) phi[j] -= phi[j] / i;
if (m == 0) return x; return __gcd(prd, n); }
ll gs = modpow(g, 1LL << (r - m - 1), p); }
vector<ull> factor(ull n) {
g = gs * gs % p;
x = x * gs % p; if (n == 1) return {}; 5.4 Fractions
b = b * g % p; if (isPrime(n)) return {n}; ContinuedFractions.h
} ull x = pollard(n); Description: Given N and a real number x ≥ 0, finds the closest rational
} auto l = factor(x), r = factor(n / x); approximation p/q with p, q ≤ N . It will obey |p/q − x| ≤ 1/qN .
l.insert(l.end(), all(r)); For consecutive convergents, pk+1 qk − qk+1 pk = (−1)k . (pk /qk alternates
return l; between > x and < x.) If x is rational, y eventually becomes ∞; if x is the
5.2 Primality } root of a degree 2 polynomial the a’s eventually become cyclic.
FastEratosthenes.h Time: O (log N ) dd6c5e, 21 lines
Description: Prime sieve for generating all primes smaller than LIM.
Time: LIM=1e9 ≈ 1.5s 6b2912, 20 lines
5.3 Divisibility typedef double d; // for N ∼ 1e7 ; long double for N ∼ 1e9
pair<ll, ll> approximate(d x, ll N) {
const int LIM = 1e6; euclid.h ll LP = 0, LQ = 1, P = 1, Q = 0, inf = LLONG_MAX; d y = x;
bitset<LIM> isPrime; Description: Finds two integers x and y, such that ax + by = gcd(a, b). If for (;;) {
vi eratosthenes() { you just need gcd, use the built in gcd instead. If a and b are coprime, then ll lim = min(P ? (N-LP) / P : inf, Q ? (N-LQ) / Q : inf),
const int S = (int)round(sqrt(LIM)), R = LIM / 2; x is the inverse of a (mod b). 33ba8f, 5 lines a = (ll)floor(y), b = min(a, lim),
vi pr = {2}, sieve(S+1); pr.reserve(int(LIM/log(LIM)*1.1)); NP = b*P + LP, NQ = b*Q + LQ;
ll euclid(ll a, ll b, ll &x, ll &y) {
vector<pii> cp; if (a > b) {
if (!b) return x = 1, y = 0, a;
for (int i = 3; i <= S; i += 2) if (!sieve[i]) { // I f b > a/2, we have a semi=convergent that gives us a
ll d = euclid(b, a % b, y, x);
cp.push_back({i, i * i / 2}); // better approximation ; i f b = a/2, we *may* have one .
return y -= a/b * x, d;
for (int j = i * i; j <= S; j += 2 * i) sieve[j] = 1; // Return {P, Q} here for a more canonical approximation .
}
} return (abs(x - (d)NP / (d)NQ) < abs(x - (d)P / (d)Q)) ?
KTH FracBinarySearch IntPerm multinomial 10
make_pair(NP, NQ) : make_pair(P, Q); 5.8 Mobius Function 6.1.4 Burnside’s lemma
}
if (abs(y = 1/(y - (d)a)) > 3*N) { 0
n is not square free Given a group G of symmetries and a set X, the number of
return {NP, NQ}; µ(n) = 1 n has even number of prime factors elements of X up to symmetry equals
}
LP = P; P = NP;
−1 n has odd number of prime factors 1 X g
|X |,
LQ = Q; Q = NQ; |G| g∈G
} Mobius Inversion:
}
X X where X g are the elements fixed by g (g.x = x).
g(n) = f (d) ⇔ f (n) = µ(d)g(n/d)
FracBinarySearch.h If f (n) counts “configurations” (of some sort) of length n, we can
Description: Given f and N , finds the smallest fraction p/q ∈ [0, 1] such d|n d|n
that f (p/q) is true, and p, q ≤ N . You may want to throw an exception from ignore rotational symmetry using G = Zn to get
f if it finds an exact solution, in which case N can be removed. Other useful formulas/forms:
Usage: fracBS([](Frac f) { return f.p>=3*f.q; }, 10); // {1,3} n−1
Time: O (log(N ))
1X 1X
g(n) = f (gcd(n, k)) = f (k)ϕ(n/k).
P
27ab3e, 25 lines
d|n µ(d) = [n = 1] (very useful) n n
struct Frac { ll p, q; }; P P k=0 k|n
g(n) = n|d f (d) ⇔ f (n) = n|d µ(d/n)g(d)
template<class F>
Frac fracBS(F f, ll N) { P n P n 6.2 Partitions and subsets
g(n) = 1≤m≤n f ( m ) ⇔ f (n) = 1≤m≤n µ(m)g( m )
bool dir = 1, A = 1, B = 1; 6.2.1 Partition function
Frac lo{0, 1}, hi{1, 1}; // Set hi to 1/0 to search (0 , N]
if (f(lo)) return lo; Number of ways of writing n as a sum of positive integers,
assert(f(hi)); disregarding the order of the summands.
while (A || B) { Combinatorial (6) X
ll adv = 0, step = 1; // move hi i f dir , e l s e lo p(0) = 1, p(n) = (−1)k+1 p(n − k(3k − 1)/2)
for (int si = 0; step; (step *= 2) >>= si) {
adv += step;
6.1 Permutations k∈Z\{0}
Frac mid{lo.p * adv + hi.p, lo.q * adv + hi.q}; 6.1.1 Factorial √
if (abs(mid.p) > N || mid.q > N || dir == !f(mid)) { p(n) ∼ 0.145/n · exp(2.56 n)
adv -= step; si = 2; n 123 4 5 6 7 8 9 10
} n! 1 2 6 24 120 720 5040 40320 362880 3628800 n 0 1 2 3 4 5 6 7 8 9 20 50 100
} p(n) 1 1 2 3 5 7 11 15 22 30 627 ∼2e5 ∼2e8
hi.p += lo.p * adv; n 11 12 13 14 15 16 17
hi.q += lo.q * adv; n! 4.0e7 4.8e8 6.2e9 8.7e10 1.3e12 2.1e13 3.6e14 6.2.2 Lucas’ Theorem
dir = !dir;
swap(lo, hi);
n 20 25 30 40 50 100 150 171 Let n, m be non-negative integers and p a prime. Write
n! 2e18 2e25 3e32 8e47 3e64 9e157 6e262 >DBL MAX n= pk + ... +n1 p + n0 and m = mk pk + ... + m1 p + m0 . Then
nkQ
A = B; B = !!adv;
} n
≡ ki=0 m ni
(mod p).
return dir ? hi : lo; IntPerm.h m i
} Description: Permutation -> integer conversion. (Not order preserving.)
Integer -> permutation can use a lookup table.
6.2.3 Binomials
5.5 Pythagorean Triples Time: O (n) 044568, 6 lines
multinomial.h k + · · · + k P
( ki )!
1 n
The Pythagorean triples are uniquely generated by int permToInt(vi& v) { Description: Computes = .
k1 , k2 , . . . , kn k1 !k2 !...kn ! a0a312, 5 lines
int use = 0, i = 0, r = 0;
2 2 2 2 ll multinomial(vi& v) {
a = k · (m − n ), b = k · (2mn), c = k · (m + n ), for(int x:v) r = r * ++i + __builtin_popcount(use & -(1<<x)),
ll c = 1, m = v.empty() ? 1 : v[0];
use |= 1 << x; // (note : minus, not ∼! )
return r; rep(i,1,sz(v)) rep(j,0,v[i]) c = c * ++m / (j+1);
with m > n > 0, k > 0, m⊥n, and either m or n even. } return c;
}
5.6 Primes 6.1.2 Cycles
p = 962592769 is such that 221 | p − 1, which may be useful. For Let gS (n) be the number of n-permutations whose cycle lengths 6.3 General purpose numbers
hashing use 970592641 (31-bit number), 31443539979727 (45-bit), all belong to the set S. Then 6.3.1 Bernoulli numbers
3006703054056749 (52-bit). There are 78498 primes less than EGF of Bernoulli numbers is B(t) = et t−1 (FFT-able).
1 000 000. ∞
!
X xn X xn B[0, . . .] = [1, − 12 , 16 , 0, − 30
1 1
, 0, 42 , . . .]
gS (n) = exp
Primitive roots exist modulo any prime power pa , except for n=0
n! n∈S
n Sums of powers:
p = 2, a > 2, and there are ϕ(ϕ(pa )) many. For p = 2, a > 2, the n m
group Z× 1 m + 1
2a is instead isomorphic to Z2 × Z2a−2 .
X X
6.1.3 Derangements nm = Bk · (n + 1)m+1−k
m + 1 k=0 k
5.7 Estimates Permutations of a set such that none of the elements appear in i=1
graph[y][p] += inc; bool dfs(int a, int L, vector<vi>& g, vi& btoa, vi& A, vi& B) {
pair<ll, ll> maxflow(int s, int t) { } if (A[a] != L) return 0;
ll totflow = 0, totcost = 0; } A[a] = -1;
while (path(s), seen[t]) { } for (int b : g[a]) if (B[b] == L + 1) {
ll fl = INF; B[b] = 0;
for (edge* x = par[t]; x; x = par[x->from]) if (btoa[b] == -1 || dfs(btoa[b], L + 1, g, btoa, A, B))
fl = min(fl, x->cap - x->flow); return btoa[b] = a, 1;
MinCut.h }
totflow += fl; Description: After running max-flow, the left side of a min-cut from s to t return 0;
for (edge* x = par[t]; x; x = par[x->from]) { is given by all vertices reachable from s, only traversing edges with positive }
x->flow += fl; residual capacity.
ed[x->to][x->rev].flow -= fl; int hopcroftKarp(vector<vi>& g, vi& btoa) {
KTH DFSMatching MinimumVertexCover WeightedMatching GeneralMatching SCC 13
int res = 0; int res = dfsMatching(g, match);
vi A(g.size()), B(btoa.size()), cur, next; vector<bool> lfound(n, true), seen(m); int r = matInv(A = mat), M = 2*N - r, fi, fj;
for (;;) { for (int it : match) if (it != -1) lfound[it] = false; assert(r % 2 == 0);
fill(all(A), 0); vi q, cover;
fill(all(B), 0); rep(i,0,n) if (lfound[i]) q.push_back(i); if (M != N) do {
cur.clear(); while (!q.empty()) { mat.resize(M, vector<ll>(M));
for (int a : btoa) if(a != -1) A[a] = -1; int i = q.back(); q.pop_back(); rep(i,0,N) {
rep(a,0,sz(g)) if(A[a] == 0) cur.push_back(a); lfound[i] = 1; mat[i].resize(M);
for (int lay = 1;; lay++) { for (int e : g[i]) if (!seen[e] && match[e] != -1) { rep(j,N,M) {
bool islast = 0; seen[e] = true; int r = rand() % mod;
next.clear(); q.push_back(match[e]); mat[i][j] = r, mat[j][i] = (mod - r) % mod;
for (int a : cur) for (int b : g[a]) { } }
if (btoa[b] == -1) { } }
B[b] = lay; rep(i,0,n) if (!lfound[i]) cover.push_back(i); } while (matInv(A = mat) != M);
islast = 1; rep(i,0,m) if (seen[i]) cover.push_back(n+i);
} assert(sz(cover) == res); vi has(M, 1); vector<pii> ret;
else if (btoa[b] != a && !B[b]) { return cover; rep(it,0,M/2) {
B[b] = lay; } rep(i,0,M) if (has[i])
next.push_back(btoa[b]); rep(j,i+1,M) if (A[i][j] && mat[i][j]) {
} WeightedMatching.h fi = i; fj = j; goto done;
} Description: Given a weighted bipartite graph, matches every node on the } assert(0); done:
if (islast) break; left with a node on the right such that no nodes are in two matchings and the if (fj < N) ret.emplace_back(fi, fj);
if (next.empty()) return res; sum of the edge weights is minimal. Takes cost[N][M], where cost[i][j] = cost has[fi] = has[fj] = 0;
for (int a : next) A[a] = lay; for L[i] to be matched with R[j] and returns (min cost, match), where L[i] is rep(sw,0,2) {
cur.swap(next); matched with R[match[i]]. Negate costs for max cost. Requires N ≤ M . ll a = modpow(A[fi][fj], mod-2);
} Time: O N 2 M
rep(i,0,M) if (has[i] && A[i][fj]) {
rep(a,0,sz(g)) 1e0fe9, 31 lines ll b = A[i][fj] * a % mod;
res += dfs(a, 0, g, btoa, A, B); pair<int, vi> hungarian(const vector<vi> &a) { rep(j,0,M) A[i][j] = (A[i][j] - A[fi][j] * b) % mod;
} if (a.empty()) return {0, {}}; }
} int n = sz(a) + 1, m = sz(a[0]) + 1; swap(fi,fj);
vi u(n), v(m), p(m), ans(n - 1); }
DFSMatching.h rep(i,1,n) { }
Description: Simple bipartite matching algorithm. Graph g should be a list p[0] = i; return ret;
of neighbors of the left partition, and btoa should be a vector full of -1’s of int j0 = 0; // add ”dummy” worker 0 }
the same size as the right partition. Returns the size of the matching. btoa[i] vi dist(m, INT_MAX), pre(m, -1);
will be the match for vertex i on the right side, or −1 if it’s not matched. vector<bool> done(m + 1);
do { // d i j k s t r a
7.4 DFS algorithms
Usage: vi btoa(m, -1); dfsMatching(g, btoa);
Time: O (V E) done[j0] = true; SCC.h
522b98, 22 lines int i0 = p[j0], j1, delta = INT_MAX; Description: Finds strongly connected components in a directed graph. If
bool find(int j, vector<vi>& g, vi& btoa, vi& vis) { rep(j,1,m) if (!done[j]) { vertices u, v belong to the same component, we can reach u from v and vice
if (btoa[j] == -1) return 1; auto cur = a[i0 - 1][j - 1] - u[i0] - v[j]; versa.
vis[j] = 1; int di = btoa[j]; if (cur < dist[j]) dist[j] = cur, pre[j] = j0; Usage: scc(graph, [&](vi& v) { ... }) visits all components
for (int e : g[di]) if (dist[j] < delta) delta = dist[j], j1 = j; in reverse topological order. comp[i] holds the component
if (!vis[e] && find(e, g, btoa, vis)) { } index of a node (a component only has edges to components with
btoa[e] = di; rep(j,0,m) { lower index). ncomps will contain the number of components.
return 1; if (done[j]) u[p[j]] += delta, v[j] -= delta; Time: O (E + V ) 76b5c9, 24 lines
} else dist[j] -= delta;
return 0; } vi val, comp, z, cont;
} j0 = j1; int Time, ncomps;
int dfsMatching(vector<vi>& g, vi& btoa) { } while (p[j0]); template<class G, class F> int dfs(int j, G& g, F& f) {
vi vis; while (j0) { // update alternating path int low = val[j] = ++Time, x; z.push_back(j);
rep(i,0,sz(g)) { int j1 = pre[j0]; for (auto e : g[j]) if (comp[e] < 0)
vis.assign(sz(btoa), 0); p[j0] = p[j1], j0 = j1; low = min(low, val[e] ?: dfs(e,g,f));
for (int j : g[i]) }
if (find(j, g, btoa, vis)) { } if (low == val[j]) {
btoa[j] = i; rep(j,1,m) if (p[j]) ans[p[j] - 1] = j - 1; do {
break; return {-v[0], ans}; // min cost x = z.back(); z.pop_back();
} } comp[x] = ncomps;
} cont.push_back(x);
return sz(btoa) - (int)count(all(btoa), -1); } while (x != j);
GeneralMatching.h f(cont); cont.clear();
} Description: Matching for general graphs. Fails with probability N/mod. ncomps++;
Time: O N 3 }
MinimumVertexCover.h "../numerical/MatrixInverse-mod.h" cb1912, 40 lines return val[j] = low;
Description: Finds a minimum vertex cover in a bipartite graph. The size vector<pii> generalMatching(int N, vector<pii>& ed) { }
is the same as the size of a maximum matching, and the complement is a vector<vector<ll>> mat(N, vector<ll>(N)), A; template<class G, class F> void scc(G& g, F f) {
maximum independent set. for (pii pa : ed) { int n = sz(g);
"DFSMatching.h" da4196, 20 lines int a = pa.first, b = pa.second, r = rand() % mod; val.assign(n, 0); comp.assign(n, -1);
vi cover(vector<vi>& g, int n, int m) { mat[a][b] = r, mat[b][a] = (mod - r) % mod; Time = ncomps = 0;
vi match(m, -1); } rep(i,0,n) if (comp[i] < 0) dfs(i, g, f);
KTH BiconnectedComponents 2sat EulerWalk EdgeColoring MaximalCliques 14
} int addVar() { // ( optional ) }}
gr.emplace_back(); for (int x : D) if (x < 0 || sz(ret) != nedges+1) return {};
gr.emplace_back(); return {ret.rbegin(), ret.rend()};
BiconnectedComponents.h return N++; }
Description: Finds all biconnected components in an undirected graph, and }
runs a callback for the edges in each. In a biconnected component there are
at least two distinct paths between any two nodes. Note that a node can be void either(int f, int j) {
in several components. An edge which is not in a component is a bridge, i.e.,
not part of any cycle.
f = max(2*f, -1-2*f); 7.5 Coloring
j = max(2*j, -1-2*j);
Usage: int eid = 0; ed.resize(N); gr[f].push_back(j^1); EdgeColoring.h
for each edge (a,b) { gr[j].push_back(f^1); Description: Given a simple, undirected graph with max degree D, com-
ed[a].emplace back(b, eid); } putes a (D + 1)-coloring of the edges such that no neighboring edges share
ed[b].emplace back(a, eid++); } void setValue(int x) { either(x, x); } a color. (D-coloring is NP-hard, but can be done for bipartite graphs by
bicomps([&](const vi& edgelist) {...}); repeated matchings of max-degree nodes.)
Time: O (E + V ) c6b7c7, 32 lines void atMostOne(const vi& li) { // ( optional ) Time: O (N M ) e210e2, 31 lines
vi num, st; if (sz(li) <= 1) return; vi edgeColoring(int N, vector<pii> eds) {
vector<vector<pii>> ed; int cur = ∼li[0]; vi cc(N + 1), ret(sz(eds)), fan(N), free(N), loc;
int Time; rep(i,2,sz(li)) { for (pii e : eds) ++cc[e.first], ++cc[e.second];
template<class F> int next = addVar(); int u, v, ncols = *max_element(all(cc)) + 1;
int dfs(int at, int par, F& f) { either(cur, ∼li[i]); vector<vi> adj(N, vi(ncols, -1));
int me = num[at] = ++Time, top = me; either(cur, next); for (pii e : eds) {
for (auto [y, e] : ed[at]) if (e != par) { either(∼li[i], next); tie(u, v) = e;
if (num[y]) { cur = ∼next; fan[0] = v;
top = min(top, num[y]); } loc.assign(ncols, 0);
if (num[y] < me) either(cur, ∼li[1]); int at = u, end = u, d, c = free[u], ind = 0, i = 0;
st.push_back(e); } while (d = free[v], !loc[d] && (v = adj[u][d]) != -1)
} else { loc[d] = ++ind, cc[ind] = d, fan[ind] = v;
int si = sz(st); vi val, comp, z; int time = 0; cc[loc[d]] = c;
int up = dfs(y, e, f); int dfs(int i) { for (int cd = d; at != -1; cd ^= c ^ d, at = adj[at][cd])
top = min(top, up); int low = val[i] = ++time, x; z.push_back(i); swap(adj[at][cd], adj[end = at][cd ^ c ^ d]);
if (up == me) { for(int e : gr[i]) if (!comp[e]) while (adj[fan[i]][d] != -1) {
st.push_back(e); low = min(low, val[e] ?: dfs(e)); int left = fan[i], right = fan[++i], e = cc[i];
f(vi(st.begin() + si, st.end())); if (low == val[i]) do { adj[u][e] = left;
st.resize(si); x = z.back(); z.pop_back(); adj[left][e] = u;
} comp[x] = low; adj[right][e] = -1;
else if (up < me) st.push_back(e); if (values[x>>1] == -1) free[right] = e;
else { /* e i s a bridge */ } values[x>>1] = x&1; }
} } while (x != i); adj[u][d] = fan[i];
} return val[i] = low; adj[fan[i]][d] = u;
return top; } for (int y : {fan[0], u, end})
} for (int& z = free[y] = 0; adj[y][z] != -1; z++);
bool solve() { }
template<class F> values.assign(N, -1); rep(i,0,sz(eds))
void bicomps(F f) { val.assign(2*N, 0); comp = val; for (tie(u, v) = eds[i]; adj[u][ret[i]] != v;) ++ret[i];
num.assign(sz(ed), 0); rep(i,0,2*N) if (!comp[i]) dfs(i); return ret;
rep(i,0,sz(ed)) if (!num[i]) dfs(i, -1, f); rep(i,0,N) if (comp[2*i] == comp[2*i+1]) return 0; }
} return 1;
}
};
2sat.h 7.6 Heuristics
Description: Calculates a valid assignment to boolean variables a,
b, c,... to a 2-SAT problem, so that an expression of the type EulerWalk.h MaximalCliques.h
(a||b)&&(!a||c)&&(d||!b)&&... becomes true, or reports that it is unsatis- Description: Eulerian undirected/directed path/cycle algorithm. Input Description: Runs a callback for all maximal cliques in a graph (given as a
fiable. Negated variables are represented by bit-inversions (∼x). should be a vector of (dest, global edge index), where for undirected graphs, symmetric bitset matrix; self-edges not allowed). Callback is given a bitset
Usage: TwoSat ts(number of boolean variables); forward/backward edges have the same index. Returns a list of nodes in representing
themaximal clique.
ts.either(0, ∼3); // Var 0 is true or var 3 is false the Eulerian path/cycle with src at both start and end, or empty list if no Time: O 3n/3 , much faster for sparse graphs
ts.setValue(2); // Var 2 is true cycle/path exists. To get edge indices back, add .second to s and ret. b0d5b1, 12 lines
ts.atMostOne({0,∼1,2}); // <= 1 of vars 0, ∼1 and 2 are true Time: O (V + E) 780b64, 15 lines typedef bitset<128> B;
ts.solve(); // Returns true iff it is solvable template<class F>
ts.values[0..N-1] holds the assigned values to the vars vi eulerWalk(vector<vector<pii>>& gr, int nedges, int src=0) {
void cliques(vector<B>& eds, F f, B P = ∼B(), B X={}, B R={}) {
Time: O (N + E), where N is the number of boolean variables, and E is the int n = sz(gr);
if (!P.any()) { if (!X.any()) f(R); return; }
number of clauses. vi D(n), its(n), eu(nedges), ret, s = {src};
5f9706, 56 lines auto q = (P | X)._Find_first();
D[src]++; // to allow Euler paths , not j u s t cycles
auto cands = P & ∼eds[q];
struct TwoSat { while (!s.empty()) {
rep(i,0,sz(eds)) if (cands[i]) {
int N; int x = s.back(), y, e, &it = its[x], end = sz(gr[x]);
R[i] = 1;
vector<vi> gr; if (it == end){ ret.push_back(x); s.pop_back(); continue; }
cliques(eds, f, P & eds[i], X & eds[i], R);
vi values; // 0 = false , 1 = true tie(y, e) = gr[x][it++];
R[i] = P[i] = 0; X[i] = 1;
if (!eu[e]) {
}
TwoSat(int n = 0) : N(n), gr(2*n) {} D[x]--, D[y]++;
}
eu[e] = 1; s.push_back(y);
KTH MaximumClique MaximumIndependentSet BinaryLifting LCA CompressTree HLD 15
MaximumClique.h vector<vi> treeJump(vi& P){ rep(i,0,m) {
Description: Quickly finds a maximum clique of a graph (given as symmet- int on = 1, d = 1; int a = li[i], b = li[i+1];
ric bitset matrix; self-edges not allowed). Can be used to find a maximum while(on < sz(P)) on *= 2, d++; li.push_back(lca.lca(a, b));
independent set by finding a clique of the complement graph. vector<vi> jmp(d, P); }
Time: Runs in about 1s for n=155 and worst case random graphs (p=.90). rep(i,1,d) rep(j,0,sz(P)) sort(all(li), cmp);
Runs faster for sparse graphs. f7c0bc, 49 lines
jmp[i][j] = jmp[i-1][jmp[i-1][j]]; li.erase(unique(all(li)), li.end());
return jmp; rep(i,0,sz(li)) rev[li[i]] = i;
typedef vector<bitset<200>> vb; } vpi ret = {pii(0, li[0])};
struct Maxclique { rep(i,0,sz(li)-1) {
double limit=0.025, pk=0; int jmp(vector<vi>& tbl, int nod, int steps){ int a = li[i], b = li[i+1];
struct Vertex { int i, d=0; }; rep(i,0,sz(tbl)) ret.emplace_back(rev[lca.lca(a, b)], b);
typedef vector<Vertex> vv; if(steps&(1<<i)) nod = tbl[i][nod]; }
vb e; return nod; return ret;
vv V; } }
vector<vi> C;
vi qmax, q, S, old; int lca(vector<vi>& tbl, vi& depth, int a, int b) {
void init(vv& r) { HLD.h
if (depth[a] < depth[b]) swap(a, b); Description: Decomposes a tree into vertex disjoint heavy paths and light
for (auto& v : r) v.d = 0; a = jmp(tbl, a, depth[a] - depth[b]);
for (auto& v : r) for (auto j : r) v.d += e[v.i][j.i]; edges such that the path from any leaf to the root contains at most log(n)
if (a == b) return a; light edges. Code does additive modifications and max queries, but can
sort(all(r), [](auto a, auto b) { return a.d > b.d; }); for (int i = sz(tbl); i--;) {
int mxD = r[0].d; support commutative segtree modifications/queries on paths and subtrees.
int c = tbl[i][a], d = tbl[i][b]; Takes as input the full adjacency list. VALS EDGES being true means that
rep(i,0,sz(r)) r[i].d = min(i, mxD) + 1; if (c != d) a = c, b = d;
} values are stored in the edges, as opposed to the nodes. All values initialized
} to the segtree default.
void expand(vv& R, int lev = 1) { return tbl[0][a]; Root must be 0.
S[lev] += S[lev - 1] - old[lev]; Time: O (log N )2
} "../data-structures/LazySegmentTree.h" 03139d, 46 lines
old[lev] = S[lev - 1];
while (sz(R)) { template <bool VALS_EDGES> struct HLD {
if (sz(q) + R.back().d <= sz(qmax)) return; LCA.h int N, tim = 0;
q.push_back(R.back().i); Description: Data structure for computing lowest common ancestors in a vector<vi> adj;
vv T; tree (with 0 as root). C should be an adjacency list of the tree, either di- vi par, siz, rt, pos;
for(auto v:R) if (e[R.back().i][v.i]) T.push_back({v.i}); rected or undirected. Node *tree;
if (sz(T)) { Time: O (N log N + Q) HLD(vector<vi> adj_)
if (S[lev]++ / ++pk < limit) init(T); "../data-structures/RMQ.h" 0f62fb, 21 lines : N(sz(adj_)), adj(adj_), par(N, -1), siz(N, 1),
int j = 0, mxk = 1, mnk = max(sz(qmax) - sz(q) + 1, 1); struct LCA { rt(N),pos(N),tree(new Node(0, N)){ dfsSz(0); dfsHld(0); }
C[1].clear(), C[2].clear(); int T = 0; void dfsSz(int v) {
for (auto v : T) { vi time, path, ret; if (par[v] != -1) adj[v].erase(find(all(adj[v]), par[v]));
int k = 1; RMQ<int> rmq; for (int& u : adj[v]) {
auto f = [&](int i) { return e[v.i][i]; }; par[u] = v;
while (any_of(all(C[k]), f)) k++; LCA(vector<vi>& C) : time(sz(C)), rmq((dfs(C,0,-1), ret)) {} dfsSz(u);
if (k > mxk) mxk = k, C[mxk + 1].clear(); void dfs(vector<vi>& C, int v, int par) { siz[v] += siz[u];
if (k < mnk) T[j++].i = v.i; time[v] = T++; if (siz[u] > siz[adj[v][0]]) swap(u, adj[v][0]);
C[k].push_back(v.i); for (int y : C[v]) if (y != par) { }
} path.push_back(v), ret.push_back(time[v]); }
if (j > 0) T[j - 1].d = 0; dfs(C, y, v); void dfsHld(int v) {
rep(k,mnk,mxk + 1) for (int i : C[k]) } pos[v] = tim++;
T[j].i = i, T[j++].d = k; } for (int u : adj[v]) {
expand(T, lev + 1); rt[u] = (u == adj[v][0] ? rt[v] : u);
} else if (sz(q) > sz(qmax)) qmax = q; int lca(int a, int b) { dfsHld(u);
q.pop_back(), R.pop_back(); if (a == b) return a; }
} tie(a, b) = minmax(time[a], time[b]); }
} return path[rmq.query(a, b)]; template <class B> void process(int u, int v, B op) {
vi maxClique() { init(V), expand(V); return qmax; } } for (; rt[u] != rt[v]; v = par[rt[v]]) {
Maxclique(vb conn) : e(conn), C(sz(e)+1), S(sz(C)), old(S) { // d i s t (a , b){return depth [ a ] + depth [ b ] = 2* depth [ lca (a , b) ] ;} if (pos[rt[u]] > pos[rt[v]]) swap(u, v);
rep(i,0,sz(e)) V.push_back({i}); }; op(pos[rt[v]], pos[v] + 1);
} }
}; if (pos[u] > pos[v]) swap(u, v);
CompressTree.h op(pos[u] + VALS_EDGES, pos[v] + 1);
Description: Given a rooted tree and a subset S of nodes, compute the }
MaximumIndependentSet.h minimal subtree that contains all the nodes by adding all (at most |S| − 1)
Description: To obtain a maximum independent set of a graph, find a max void modifyPath(int u, int v, int val) {
pairwise LCA’s and compressing edges. Returns a list of (par, orig index) process(u, v, [&](int l, int r) { tree->add(l, r, val); });
clique of the complement. If the graph is bipartite, see MinimumVertex- representing a tree rooted at 0. The root points to itself.
Cover. }
Time: O (|S| log |S|) int queryPath(int u, int v) { // Modify depending on problem
"LCA.h" 9775a0, 21 lines int res = -1e9;
typedef vector<pair<int, int>> vpi; process(u, v, [&](int l, int r) {
7.7 Trees vpi compressTree(LCA& lca, const vi& subset) { res = max(res, tree->query(l, r));
BinaryLifting.h static vi rev; rev.resize(sz(lca.time)); });
Description: Calculate power of two jumps in a tree, to support fast up- vi li = subset, &T = lca.time; return res;
ward jumps and LCAs. Assumes the root node points to itself. auto cmp = [&](int a, int b) { return T[a] < T[b]; }; }
Time: construction O (N log N ), queries O (log N ) sort(all(li), cmp); int querySubtree(int v) { // modifySubtree i s similar
bfce85, 25 lines
int m = sz(li)-1; return tree->query(pos[v] + VALS_EDGES, pos[v] + siz[v]);
KTH LinkCutTree DirectedMST Point 16
} x->c[0] = top->p = 0; while (seen[u] < 0) {
}; x->fix(); if (!heap[u]) return {-1,{}};
} Edge e = heap[u]->top();
} heap[u]->delta -= e.w, pop(heap[u]);
LinkCutTree.h bool connected(int u, int v) { // are u, v in the same tree? Q[qi] = e, path[qi++] = u, seen[u] = s;
Description: Represents a forest of unrooted trees. You can add and re- Node* nu = access(&node[u])->first(); res += e.w, u = uf.find(e.a);
move edges (as long as the result is still a forest), and check whether two return nu == access(&node[v])->first(); if (seen[u] == s) {
nodes are in the same tree. } Node* cyc = 0;
Time: All operations take amortized O (log N ). 0fb462, 90 lines
void makeRoot(Node* u) { int end = qi, time = uf.time();
access(u); do cyc = merge(cyc, heap[w = path[--qi]]);
struct Node { // Splay tree . Root ’ s pp contains tree ’ s parent . u->splay(); while (uf.join(u, w));
Node *p = 0, *pp = 0, *c[2]; if(u->c[0]) { u = uf.find(u), heap[u] = cyc, seen[u] = -1;
bool flip = 0; u->c[0]->p = 0; cycs.push_front({u, time, {&Q[qi], &Q[end]}});
Node() { c[0] = c[1] = 0; fix(); } u->c[0]->flip ^= 1; }
void fix() { u->c[0]->pp = u; }
if (c[0]) c[0]->p = this; u->c[0] = 0; rep(i,0,qi) in[uf.find(Q[i].b)] = Q[i];
if (c[1]) c[1]->p = this; u->fix(); }
// (+ update sum of subtree elements etc . i f wanted) }
} } for (auto& [u,t,comp] : cycs) { // restore so l ( optional )
void pushFlip() { Node* access(Node* u) { uf.rollback(t);
if (!flip) return; u->splay(); Edge inEdge = in[u];
flip = 0; swap(c[0], c[1]); while (Node* pp = u->pp) { for (auto& e : comp) in[uf.find(e.b)] = e;
if (c[0]) c[0]->flip ^= 1; pp->splay(); u->pp = 0; in[uf.find(inEdge.b)] = inEdge;
if (c[1]) c[1]->flip ^= 1; if (pp->c[1]) { }
} pp->c[1]->p = 0; pp->c[1]->pp = pp; } rep(i,0,n) par[i] = in[i].a;
int up() { return p ? p->c[1] == this : -1; } pp->c[1] = u; pp->fix(); u = pp; return {res, par};
void rot(int i, int b) { } }
int h = i ^ b; return u;
Node *x = c[i], *y = b == 2 ? x : x->c[h], *z = b ? y : x;
if ((y->p = p)) p->c[up()] = y;
} 7.8 Math
};
c[i] = z->c[i ^ 1]; 7.8.1 Number of Spanning Trees
if (b < 2) {
x->c[h] = y->c[h ^ 1]; DirectedMST.h Create an N × N matrix mat, and for each edge a → b ∈ G, do
y->c[h ^ 1] = x; Description: Finds a minimum spanning tree/arborescence of a directed mat[a][b]--, mat[b][b]++ (and mat[b][a]--,
} graph, given a root node. If no MST exists, returns -1.
z->c[i ^ 1] = this; Time: O (E log V ) mat[a][a]++ if G is undirected). Remove the ith row and
fix(); x->fix(); y->fix(); "../data-structures/UnionFindRollback.h" 39e620, 60 lines column and take the determinant; this yields the number of
if (p) p->fix(); struct Edge { int a, b; ll w; }; directed spanning trees rooted at i (if G is undirected, remove
swap(pp, y->pp); struct Node {
} Edge key; any row/column).
void splay() { Node *l, *r;
for (pushFlip(); p; ) { ll delta; 7.8.2 Erdős–Gallai theorem
if (p->p) p->p->pushFlip(); void prop() { A simple graph with node degrees d1 ≥ · · · ≥ dn exists iff
p->pushFlip(); pushFlip(); key.w += delta;
int c1 = up(), c2 = p->up(); if (l) l->delta += delta;
d1 + · · · + dn is even and for every k = 1 . . . n,
if (c2 == -1) p->rot(c1, 2); if (r) r->delta += delta; k n
else p->p->rot(c2, c1 != c2); delta = 0; X X
} } di ≤ k(k − 1) + min(di , k).
} Edge top() { prop(); return key; } i=1 i=k+1
Node* first() { };
pushFlip(); Node *merge(Node *a, Node *b) {
return c[0] ? c[0]->first() : (splay(), this); if (!a || !b) return a ?: b;
};
} a->prop(), b->prop();
if (a->key.w > b->key.w) swap(a, b);
Geometry (8)
swap(a->l, (a->r = merge(b, a->r)));
struct LinkCut { return a; 8.1 Geometric primitives
vector<Node> node; } Point.h
LinkCut(int N) : node(N) {} void pop(Node*& a) { a->prop(); a = merge(a->l, a->r); } Description: Class to handle points in the plane. T can be e.g. double or
long long. (Avoid int.) 47ec0a, 28 lines
void link(int u, int v) { // add an edge (u, v) pair<ll, vi> dmst(int n, int r, vector<Edge>& g) {
assert(!connected(u, v)); RollbackUF uf(n); template <class T> int sgn(T x) { return (x > 0) - (x < 0); }
makeRoot(&node[u]); vector<Node*> heap(n); template<class T>
node[u].pp = &node[v]; for (Edge e : g) heap[e.b] = merge(heap[e.b], new Node{e}); struct Point {
} ll res = 0; typedef Point P;
void cut(int u, int v) { // remove an edge (u, v) vi seen(n, -1), path(n), par(n); T x, y;
Node *x = &node[u], *top = &node[v]; seen[r] = r; explicit Point(T x=0, T y=0) : x(x), y(y) {}
makeRoot(top); x->splay(); vector<Edge> Q(n), in(n, {-1,-1}), comp; bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); }
assert(top == (x->pp ?: x->c[0])); deque<tuple<int, int, vector<Edge>>> cycs; bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); }
if (x->pp) x->pp = 0; rep(s,0,n) { P operator+(P p) const { return P(x+p.x, y+p.y); }
else { int u = s, qi = 0, w; P operator-(P p) const { return P(x-p.x, y-p.y); }
KTH lineDistance SegmentDistance SegmentIntersection lineIntersection sideOf OnSegment linearTransformation Angle CircleIntersection 17
P operator*(T d) const { return P(x*d, y*d); } if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0) P dp = p1-p0, dq = q1-q0, num(dp.cross(dq), dp.dot(dq));
P operator/(T d) const { return P(x/d, y/d); } return {(a * ob - b * oa) / (ob - oa)}; return q0 + P((r-p0).cross(num), (r-p0).dot(num))/dp.dist2();
T dot(P p) const { return x*p.x + y*p.y; } set<P> s; }
T cross(P p) const { return x*p.y - y*p.x; } if (onSegment(c, d, a)) s.insert(a);
T cross(P a, P b) const { return (a-*this).cross(b-*this); } if (onSegment(c, d, b)) s.insert(b);
T dist2() const { return x*x + y*y; } if (onSegment(a, b, c)) s.insert(c); Angle.h
double dist() const { return sqrt((double)dist2()); } if (onSegment(a, b, d)) s.insert(d); Description: A class for ordering angles (as represented by int points and
// angle to x=axis in interval [= pi , pi ] return {all(s)}; a number of rotations around the origin). Useful for rotational sweeping.
double angle() const { return atan2(y, x); } } Sometimes also represents points or vectors.
P unit() const { return *this/dist(); } // makes d i s t ()=1 Usage: vector<Angle> v = {w[0], w[0].t360() ...}; // sorted
P perp() const { return P(-y, x); } // rotates +90 degrees
P normal() const { return perp().unit(); }
lineIntersection.h int j = 0; rep(i,0,n) { while (v[j] < v[i].t180()) ++j; }
Description: // sweeps j such that (j-i) represents the number of positively
// returns point rotated ’a ’ radians ccw around the origin oriented triangles with vertices at 0 and i
If a unique intersection point of the lines going through s1,e1 0f0602, 35 lines
P rotate(double a) const {
and s2,e2 exists {1, point} is returned. If no intersection point
return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); } struct Angle {
exists {0, (0,0)} is returned and if infinitely many exists {-1, e2 r
friend ostream& operator<<(ostream& os, P p) { int x, y;
(0,0)} is returned. The wrong position will be returned if P
return os << "(" << p.x << "," << p.y << ")"; }
is Point<ll> and the intersection point does not have integer e1 s2 int t;
coordinates. Products of three coordinates are used in inter- s1
}; Angle(int x, int y, int t=0) : x(x), y(y), t(t) {}
Angle operator-(Angle b) const { return {x-b.x, y-b.y, t}; }
mediate steps so watch out for overflow if using int or ll.
int half() const {
lineDistance.h Usage: auto res = lineInter(s1,e1,s2,e2);
assert(x || y);
Description: if (res.first == 1)
cout << "intersection point at " << res.second << endl; return y < 0 || (y == 0 && x < 0);
Returns the signed distance between point p and the line con-
}
taining points a and b. Positive value on left side and negative "Point.h" a01f81, 8 lines
on right as seen from a towards b. a==b gives nan. P is sup-
res Angle t90() const { return {-y, x, t + (half() && x >= 0)}; }
template<class P>
posed to be Point<T> or Point3D<T> where T is e.g. double e p pair<int, P> lineInter(P s1, P e1, P s2, P e2) {
Angle t180() const { return {-x, -y, t + half()}; }
Angle t360() const { return {x, y, t + 1}; }
or long long. It uses products in intermediate steps so watch auto d = (e1 - s1).cross(e2 - s2); };
out for overflow if using int or long long. Using Point3D will if (d == 0) // i f p a r a l l e l
always give a non-negative distance. For Point3D, call .dist s
bool operator<(Angle a, Angle b) {
return {-(s1.cross(e1, s2) == 0), P(0, 0)}; // add a . dist2 () and b . dist2 () to also compare distances
on the result of the cross product. auto p = s2.cross(e1, e2), q = s2.cross(e2, s1);
"Point.h" f6bf6b, 4 lines return make_tuple(a.t, a.half(), a.y * (ll)b.x) <
return {1, (s1 * p + e1 * q) / d}; make_tuple(b.t, b.half(), a.x * (ll)b.y);
template<class P> } }
double lineDist(const P& a, const P& b, const P& p) {
return (double)(b-a).cross(p-a)/(b-a).dist();
} sideOf.h // Given two points , t h i s calculates the smallest angle between
Description: Returns where p is as seen from s towards e. 1/0/-1 ⇔ left/on // them, i . e . , the angle that covers the defined l i n e segment .
e res p
line/right. If the optional argument eps is given 0 is returned if p is within pair<Angle, Angle> segmentAngles(Angle a, Angle b) {
SegmentDistance.h distance eps from the line. P is supposed to be Point<T> where T is e.g. if (b < a) swap(a, b);
Description: double or long long. It uses products in intermediate steps so watch out for return (b < a.t180() ?
Returns the shortest distance between point p and the line overflow if using int or long long. make_pair(a, b) : make_pair(b, a.t360()));
segment from point s to e. s Usage: bool left = sideOf(p1,p2,q)==1; }
Usage: Point<double> a, b(2,2), p(1,1); "Point.h" 3af81c, 9 lines Angle operator+(Angle a, Angle b) { // point a + vector b
bool onSegment = segDist(a,b,p) < 1e-10; Angle r(a.x + b.x, a.y + b.y, a.t);
"Point.h" 5c88f4, 6 lines
template<class P>
int sideOf(P s, P e, P p) { return sgn(s.cross(e, p)); } if (a.t180() < r) r.t--;
typedef Point<double> P; return r.t180() < a ? r.t360() : r;
double segDist(P& s, P& e, P& p) { template<class P> }
if (s==e) return (p-s).dist(); int sideOf(const P& s, const P& e, const P& p, double eps) { Angle angleDiff(Angle a, Angle b) { // angle b = angle a
auto d = (e-s).dist2(), t = min(d,max(.0,(p-s).dot(e-s))); auto a = (e-s).cross(p-s); int tu = b.t - a.t; a.t = b.t;
return ((p-s)*d-(e-s)*t).dist()/d; double l = (e-s).dist()*eps; return {a.x*b.x + a.y*b.y, a.x*b.y - a.y*b.x, tu - (b < a)};
} return (a > l) - (a < -l); }
}
SegmentIntersection.h
Description: OnSegment.h
If a unique intersection point between the line segments going
Description: Returns true iff p lies on the line segment from s to e. Use
8.2 Circles
from s1 to e1 and from s2 to e2 exists then it is returned. CircleIntersection.h
(segDist(s,e,p)<=epsilon) instead when using Point<double>.
If no intersection point exists an empty vector is returned. e1 "Point.h" c597e8, 3 lines Description: Computes the pair of points at which two circles intersect.
If infinitely many exist a vector with 2 elements is returned,
containing the endpoints of the common line segment. The e2 template<class P> bool onSegment(P s, P e, P p) { Returns false in case of no intersection.
wrong position will be returned if P is Point<ll> and the in- r1 return p.cross(s, e) == 0 && (s - p).dot(e - p) <= 0; "Point.h" 84d6d3, 11 lines