├── .gitignore ├── BST ├── RedBlackTree.cpp ├── RedBlackTree.h ├── TwoThreeTree.cpp └── TwoThreeTree.h ├── CodingExercise ├── chess_bottom_up.cpp └── chess_top_down.cpp ├── DP ├── DP_DivideAndConquer.h ├── LiChaoTree.h ├── LiChaoTreeDynamic.h └── MinQueue.h ├── Geometry ├── Area.h ├── Geometry.h ├── GrahamScan.h ├── Polygon.h └── Rotations.h ├── Graphs ├── BFS.h ├── Bipartite.h ├── BlockCutTree.h ├── Bridge_CutPoint.h ├── CatesianTreeMax.h ├── DFS.h ├── Dijkstra.h ├── DivideAndConquer.h ├── EdmondKarp.h ├── FindOddCycle.h ├── Floyd-Warshall.h ├── HLD.h ├── HopcroftKarp.h ├── Kruskal.h ├── LCA.h ├── LCA_Binary_Lifting.h ├── LCA_Farach_Colton_Bender.h ├── MinCostMaxFlow.h ├── MinCostMaxFlowMultipleEdges.h ├── SCC.h ├── TopologicalSort.h ├── TwoSAT.h ├── UnionFind.h ├── UnionFindWithSets.h └── lca.cpp ├── LICENSE ├── Math ├── ArithmeticSeries.h ├── BigInteger.h ├── BinomialCoefficient.h ├── CRT.h ├── DiscreteLog.h ├── DiscreteLogs.h ├── Divisors.h ├── Exponentiation.h ├── ExtendedEuclid.h ├── FFT.h ├── Factorial.h ├── FastBinomialCoefficient.h ├── FloorCeilDivision.h ├── Fraction.h ├── GeometricSeries.h ├── InverseModPrime.h ├── IsPrime.h ├── LinearDiophantine.h ├── Matrix.h ├── Matrix2.h ├── MatrixStrassen.h ├── MatrixTransition.h ├── MillerRabin.h ├── MillerRabin64.h ├── Modular.h ├── MontgomeryModular.h ├── NegativeBase.h ├── NevilleInterpolation.h ├── NevilleInterpolationPolynomial.h ├── Polynomial.h ├── PowerSums.h ├── PrimeLargest.h ├── Primes.h ├── RankBitset.h ├── Rho.h ├── SlowPolynomial.h ├── SquareRoot.h ├── SternBrocotSmallestBetween.h ├── Stirling2nd.h ├── Totient.h ├── TotientSieve.h └── moebius.h ├── Other ├── Bitset.h ├── MonotoneStorage.h ├── SegmentSet.h ├── TwoColorPartition.h └── VeniceSet.h ├── README.md ├── RangeQuery ├── BIT.h ├── BIT_Range_Updates.h ├── BinaryIndexedTree.cpp ├── BinaryIndexedTree.py ├── HashingSegmentTree.h ├── ImplicitSegmentTree.h ├── MaxPrefixSegmentTree.h ├── PersistentSegmentTree.h ├── SegmentTree.cpp ├── SegmentTree.java ├── SegmentTree.py ├── SegmentTreeAbstract.h ├── SegmentTreeDynamic.h ├── SegmentTreeMin.h ├── SegmentTreeRec.h ├── SegmentTreeRecLazyLinearFunktion.h ├── SegmentTreeRecLazyMin.h ├── SegmentTreeRecLazySum.h ├── SegmentTreeSum.h ├── SparseTable.cpp ├── SparseTable.h ├── WaveletTree.cpp └── WaveletTree.h ├── Strings ├── AhoCorasick.h ├── DeBruijn.h ├── Hashing.h ├── HashingMult.h ├── PrefixAutomaton.h └── SuffixArray.h ├── Trie ├── BinaryTrie.h ├── PersistentBinaryCountTrie.h ├── PersistentStringTrie.h └── StringTrie.h ├── autoload └── alg_ds.vim ├── demonstration.gif ├── plugin └── alg_ds.vim └── prettyprint.py /.gitignore: -------------------------------------------------------------------------------- 1 | a.out 2 | **.swp 3 | -------------------------------------------------------------------------------- /BST/RedBlackTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "RedBlackTree.h" 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | RedBlackTree tree; 8 | tree.insert(5); 9 | tree.insert(3); 10 | tree.insert(2); 11 | tree.insert(8); 12 | tree.insert(10); 13 | tree.insert(9); 14 | cout << tree.contains(1) << endl; 15 | cout << tree.contains(10) << endl; 16 | cout << tree.contains(9) << endl; 17 | cout << tree.contains(4) << endl; 18 | } 19 | -------------------------------------------------------------------------------- /BST/RedBlackTree.h: -------------------------------------------------------------------------------- 1 | 2 | template 3 | class RedBlackTreeNode 4 | { 5 | public: 6 | RedBlackTreeNode(T elem) 7 | : elem(elem), left(nullptr), right(nullptr), color(Color::red) 8 | { 9 | } 10 | 11 | static RedBlackTreeNode *rotateLeft(RedBlackTreeNode *h) 12 | { 13 | // h x 14 | // / \\ / \ 15 | // a x => h c 16 | // / \ / \ 17 | // b c a b 18 | RedBlackTreeNode *x = h->right; 19 | h->right = x->left; 20 | x->left = h; 21 | x->color = h->color; 22 | h->color = Color::red; 23 | return x; 24 | } 25 | 26 | static RedBlackTreeNode *rotateRight(RedBlackTreeNode *h) 27 | { 28 | RedBlackTreeNode *x = h->left; 29 | h->left = x->right; 30 | x->right = h; 31 | x->color = h->color; 32 | h->color = Color::red; 33 | return x; 34 | } 35 | 36 | static void flipColors(RedBlackTreeNode *h) 37 | { 38 | h->color = Color::red; 39 | h->left->color = Color::black; 40 | h->right->color = Color::black; 41 | } 42 | 43 | static bool isRed(RedBlackTreeNode *node) 44 | { 45 | if (node == nullptr) 46 | return false; 47 | return node->color == Color::red; 48 | } 49 | 50 | static RedBlackTreeNode *insert(RedBlackTreeNode *node, T elem) 51 | { 52 | if (node == nullptr) { 53 | return new RedBlackTreeNode(elem); 54 | } 55 | if (elem < node->elem) 56 | node->left = insert(node->left, elem); 57 | else 58 | node->right = insert(node->right, elem); 59 | 60 | if (!isRed(node->left) && isRed(node->right)) 61 | node = rotateLeft(node); 62 | 63 | if (isRed(node->left) && isRed(node->right)) 64 | flipColors(node); 65 | 66 | return node; 67 | } 68 | 69 | static bool contains(RedBlackTreeNode *node, T elem) 70 | { 71 | if (node == nullptr) 72 | return false; 73 | 74 | if (elem < node->elem) 75 | return contains(node->left, elem); 76 | else if (elem == node->elem) 77 | return true; 78 | else 79 | return contains(node->right, elem); 80 | } 81 | 82 | private: 83 | enum Color { black, red }; 84 | 85 | T elem; 86 | RedBlackTreeNode *left, *right; 87 | Color color; 88 | }; 89 | 90 | template 91 | class RedBlackTree 92 | { 93 | public: 94 | RedBlackTree() : root(nullptr) {} 95 | 96 | void insert(T elem) 97 | { 98 | if (root == nullptr) { 99 | root = new RedBlackTreeNode(elem); 100 | } else { 101 | root = RedBlackTreeNode::insert(root, elem); 102 | } 103 | } 104 | 105 | bool contains(T elem) 106 | { 107 | if (root == nullptr) { 108 | return false; 109 | } else { 110 | return RedBlackTreeNode::contains(root, elem); 111 | } 112 | } 113 | 114 | private: 115 | RedBlackTreeNode *root; 116 | }; 117 | -------------------------------------------------------------------------------- /BST/TwoThreeTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "TwoThreeTree.h" 3 | 4 | 5 | int main() { 6 | TwoThreeTree tree; 7 | tree.insert(5); 8 | tree.insert(3); 9 | tree.insert(2); 10 | tree.insert(4); 11 | tree.insert(6); 12 | std::cout << tree.contains(6) << std::endl; 13 | std::cout << tree.contains(1) << std::endl; 14 | } 15 | -------------------------------------------------------------------------------- /BST/TwoThreeTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | template 5 | class TwoThreeTreeNode 6 | { 7 | public: 8 | TwoThreeTreeNode(T elem) { 9 | elements[0] = elem; 10 | size = 1; 11 | children = { nullptr }; 12 | } 13 | 14 | bool insert(T elem) { 15 | if (isLeaf()) { 16 | elements[size] = elem; 17 | for (int i = size - 1; i >= 0; i--) { 18 | if (elements[i] > elements[i+1]) 19 | std::swap(elements[i], elements[i+1]); 20 | } 21 | size++; 22 | } else { 23 | int idx = 0; 24 | for (int i = 0; i < size; i++) { 25 | if (elem >= elements[i]) { 26 | idx++; 27 | } 28 | } 29 | bool three_node = children[idx]->insert(elem); 30 | if (!three_node) { 31 | auto child_left = children[idx]; 32 | child_left->size = 1; 33 | auto child_right = new TwoThreeTreeNode(child_left->elements[2]); 34 | child_right->children[0] = child_left->children[2]; 35 | child_left->children[2] = nullptr; 36 | child_right->children[1] = child_left->children[3]; 37 | child_left->children[3] = nullptr; 38 | T new_elem = child_left->elements[1]; 39 | for (int i = size - 1; i >= idx; i--) { 40 | elements[i + 1] = elements[i]; 41 | children[i + 2] = children[i + 1]; 42 | } 43 | elements[idx] = new_elem; 44 | children[idx + 1] = child_right; 45 | size++; 46 | } 47 | } 48 | 49 | return size < 3; 50 | } 51 | 52 | bool contains(T elem) { 53 | if (isLeaf()) { 54 | for (int i = 0; i < size; i++) { 55 | if (elem == elements[i]) 56 | return true; 57 | } 58 | return false; 59 | } else { 60 | for (int i = size - 1; i >= 0; i--) { 61 | if (elem > elements[i]) 62 | return children[i + 1]->contains(elem); 63 | if (elem == elements[i]) 64 | return true; 65 | } 66 | return children[0]->contains(elem); 67 | } 68 | } 69 | 70 | 71 | bool isLeaf() { 72 | return children[0] == nullptr; 73 | } 74 | 75 | std::array elements; 76 | int size; 77 | std::array*, 4> children; 78 | }; 79 | 80 | 81 | template 82 | class TwoThreeTree 83 | { 84 | public: 85 | void insert(T elem) { 86 | if (root) { 87 | bool three_node = root->insert(elem); 88 | if (!three_node) { 89 | auto child_left = root; 90 | child_left->size = 1; 91 | auto child_right = new TwoThreeTreeNode(child_left->elements[2]); 92 | child_right->children[0] = child_left->children[2]; 93 | child_left->children[2] = nullptr; 94 | child_right->children[1] = child_left->children[3]; 95 | child_left->children[3] = nullptr; 96 | T new_elem = child_left->elements[1]; 97 | root = new TwoThreeTreeNode(new_elem); 98 | root->children[0] = child_left; 99 | root->children[1] = child_right; 100 | height++; 101 | } 102 | } else { 103 | root = new TwoThreeTreeNode(elem); 104 | height = 1; 105 | } 106 | } 107 | 108 | bool contains(T elem) { 109 | if (root) 110 | return root->contains(elem); 111 | else 112 | return false; 113 | } 114 | 115 | private: 116 | TwoThreeTreeNode* root = nullptr; 117 | int height = 0; 118 | }; 119 | -------------------------------------------------------------------------------- /CodingExercise/chess_bottom_up.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | bool states[15][15] = {{false}}; 6 | for (int diag = 0; diag < 29; diag++) { 7 | int x = diag < 15 ? diag : 14; 8 | int y = diag < 15 ? 0 : diag - 14; 9 | 10 | for (; x >= 0 && y < 15; x--, y++) { 11 | bool state = false; 12 | if (x - 2 >= 0 && y + 1 < 15 && states[x-2][y+1] == false) 13 | state = true; 14 | if (x - 2 >= 0 && y - 1 >= 0 && states[x-2][y-1] == false) 15 | state = true; 16 | if (x + 1 < 15 && y - 2 >= 0 && states[x+1][y-2] == false) 17 | state = true; 18 | if (x - 1 >= 0 && y - 2 >= 0 && states[x-1][y-2] == false) 19 | state = true; 20 | states[x][y] = state; 21 | } 22 | } 23 | 24 | int T; 25 | cin >> T; 26 | while (T --> 0) { 27 | int x, y; 28 | cin >> x >> y; 29 | cout << (states[x-1][y-1] ? "First" : "Second") << endl; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CodingExercise/chess_top_down.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | map, bool> dp; 6 | 7 | bool compute_state(int x, int y) { 8 | if (dp.count({x, y})) 9 | return dp[{x, y}]; 10 | 11 | bool state = false; 12 | if (x - 2 >= 0 && y + 1 < 15 && compute_state(x-2, y+1) == false) 13 | state = true; 14 | if (x - 2 >= 0 && y - 1 >= 0 && compute_state(x-2, y-1) == false) 15 | state = true; 16 | if (x + 1 < 15 && y - 2 >= 0 && compute_state(x+1, y-2) == false) 17 | state = true; 18 | if (x - 1 >= 0 && y - 2 >= 0 && compute_state(x-1, y-2) == false) 19 | state = true; 20 | return dp[{x, y}] = state; 21 | } 22 | 23 | int main() { 24 | int T; 25 | cin >> T; 26 | while (T --> 0) { 27 | int x, y; 28 | cin >> x >> y; 29 | cout << (compute_state(x-1, y-1) ? "First" : "Second") << endl; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DP/DP_DivideAndConquer.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int dp[21][4001]; 4 | 5 | int f(int l, int r); 6 | 7 | void solve(int k, int l, int r, int optl, int optr) { 8 | if (l > r) return; 9 | int m = (l + r) >> 1; 10 | int opt = optl; 11 | int best_value = std::numeric_limits::max(); 12 | for (int i = optl; i <= std::min(optr, m); i++) { 13 | int value = dp[k-1][i-1] + f(i, m); 14 | if (value < best_value) { 15 | opt = i; 16 | best_value = value; 17 | } 18 | } 19 | dp[k][m] = best_value; 20 | solve(k, l, m-1, optl, opt); 21 | solve(k, m+1, r, opt, optr); 22 | } 23 | 24 | int main() { 25 | int n = 4000, K = 20; 26 | dp[0][0] = 0; 27 | for (int i = 1; i <= n; i++) 28 | dp[0][i] = std::numeric_limits::max() / 2; 29 | 30 | for (int k = 1; k <= K; k++) { 31 | solve(k, 1, n, 1, n); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DP/LiChaoTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Line { 5 | long long k, d; 6 | 7 | long long eval(int x) { 8 | return k * x + d; 9 | } 10 | }; 11 | 12 | class LiChaoTree { 13 | public: 14 | LiChaoTree(int n) : n(n) { 15 | inf = {0LL, std::numeric_limits::max() / 2}; 16 | lines.resize(4 * n); 17 | reset(); 18 | } 19 | 20 | void reset() { 21 | fill(lines.begin(), lines.end(), inf); 22 | } 23 | 24 | void add_line(Line new_line, int id=1, int l=0, int r=-1) { 25 | if (r == -1) 26 | r = n; 27 | 28 | int m = (l + r) / 2; 29 | bool left = new_line.eval(l) < lines[id].eval(l); 30 | bool middle = new_line.eval(m) < lines[id].eval(m); 31 | if (middle) 32 | std::swap(lines[id], new_line); 33 | 34 | if (r - l == 1) 35 | return; 36 | 37 | if (left != middle) 38 | add_line(new_line, id << 1, l, m); 39 | else 40 | add_line(new_line, id << 1 | 1, m, r); 41 | } 42 | 43 | long long get_minimum(int x, int id=1, int l=0, int r=-1) { 44 | if (r == -1) 45 | r = n; 46 | 47 | long long seg_value = lines[id].eval(x); 48 | if (r - l == 1) 49 | return seg_value; 50 | 51 | int m = (l + r) / 2; 52 | if (x < m) 53 | return std::min(seg_value, get_minimum(x, id << 1, l, m)); 54 | else 55 | return std::min(seg_value, get_minimum(x, id << 1 | 1, m, r)); 56 | } 57 | 58 | int n; 59 | std::vector lines; 60 | Line inf; 61 | }; 62 | -------------------------------------------------------------------------------- /DP/LiChaoTreeDynamic.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Line { 5 | long long k, d; 6 | 7 | long long eval(int x) { 8 | return k * x + d; 9 | } 10 | }; 11 | 12 | class LiChaoNode { 13 | public: 14 | LiChaoNode(Line line) : line(line) {} 15 | 16 | void add_line(Line new_line, int l, int r) { 17 | int m = (l + r) / 2; 18 | bool left_smaller = new_line.eval(l) < line.eval(l); 19 | bool middle_smaller = new_line.eval(m) < line.eval(m); 20 | if (middle_smaller) 21 | std::swap(line, new_line); 22 | 23 | if (r - l == 1) 24 | return; 25 | 26 | if (left_smaller != middle_smaller) { 27 | if (left == nullptr) 28 | left = new LiChaoNode(new_line); 29 | else 30 | left->add_line(new_line, l, m); 31 | } else { 32 | if (right == nullptr) 33 | right = new LiChaoNode(new_line); 34 | else 35 | right->add_line(new_line, m, r); 36 | } 37 | } 38 | 39 | long long get_minimum(int x, int l, int r) { 40 | long long val = line.eval(x); 41 | int m = (l + r) / 2; 42 | if (r - l > 1) { 43 | if (x < m && left != nullptr) 44 | val = std::min(val, left->get_minimum(x, l, m)); 45 | if (x >= m && right != nullptr) 46 | val = std::min(val, right->get_minimum(x, m, r)); 47 | } 48 | return val; 49 | } 50 | 51 | void extinguish() { 52 | if (left != nullptr) 53 | left->extinguish(); 54 | if (right != nullptr) 55 | right->extinguish(); 56 | delete this; 57 | } 58 | 59 | private: 60 | Line line; 61 | LiChaoNode* left = nullptr; 62 | LiChaoNode* right = nullptr; 63 | }; 64 | 65 | class LiChaoTree 66 | { 67 | public: 68 | LiChaoTree(int mi, int ma) : mi(mi), ma(ma) { 69 | root = new LiChaoNode({0, std::numeric_limits::max() / 2}); 70 | } 71 | 72 | ~LiChaoTree() { 73 | root->extinguish(); 74 | } 75 | 76 | void add_line(Line line) { 77 | root->add_line(line, mi, ma + 1); 78 | } 79 | 80 | long long get_minimum(int x) { 81 | return root->get_minimum(x, mi, ma + 1); 82 | } 83 | 84 | private: 85 | int mi, ma; 86 | LiChaoNode* root; 87 | }; 88 | -------------------------------------------------------------------------------- /DP/MinQueue.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class MinQueue { 4 | public: 5 | MinQueue(int capacity = 1'000'000'000) : capacity(capacity) {} 6 | 7 | int min() { 8 | return dq.front().first; 9 | } 10 | 11 | void add(int elem) { 12 | while (!dq.empty() && dq.back().first > elem) { 13 | dq.pop_back(); 14 | } 15 | dq.push_back({elem, added}); 16 | added++; 17 | if (added - removed > capacity) 18 | remove(); 19 | } 20 | 21 | void remove() { 22 | if (!dq.empty() && dq.front().second == removed) 23 | dq.pop_front(); 24 | removed++; 25 | } 26 | 27 | private: 28 | std::deque> dq; 29 | int added = 0; 30 | int removed = 0; 31 | int capacity; 32 | }; 33 | -------------------------------------------------------------------------------- /Geometry/Area.h: -------------------------------------------------------------------------------- 1 | #include "Geometry.h" 2 | 3 | double det(Vector const& v, Vector const& u) { 4 | return v.x*u.y - v.y*u.x; 5 | } 6 | 7 | double area_parallelogram(Point const& p1, Point const& p2, Point const& p3) { 8 | return std::abs(det(p2 - p1, p3 - p2)); 9 | } 10 | 11 | double area_triangle(Point const& p1, Point const& p2, Point const& p3) { 12 | return area_parallelogram(p1, p2, p3) / 2; 13 | } 14 | -------------------------------------------------------------------------------- /Geometry/Geometry.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | constexpr double EPS = 1e-9; 7 | 8 | template 9 | T det(T a11, T a12, T a21, T a22) { 10 | return a11 * a22 - a12 * a21; 11 | } 12 | 13 | template 14 | T sq(T x) { 15 | return x * x; 16 | } 17 | 18 | template 19 | class Vector2D { 20 | public: 21 | Vector2D(T x=0, T y=0) : x(x), y(y) {} 22 | 23 | Vector2D& operator+=(Vector2D const& v) { x += v.x; y += v.y; return *this; } 24 | Vector2D operator+(Vector2D const& v) const { Vector2D u = *this; u += v; return u; } 25 | Vector2D& operator-=(Vector2D const& v) { x -= v.x; y -= v.y; return *this; } 26 | Vector2D operator-(Vector2D const& v) const { Vector2D u = *this; u -= v; return u; } 27 | Vector2D& operator*=(T const c) { x *= c; y *= c; return *this; } 28 | Vector2D operator*(T const& c) const { Vector2D u = *this; u *= c; return u; } 29 | Vector2D& operator/=(T const c) { x /= c; y /= c; return *this; } 30 | Vector2D operator/(T const& c) const { Vector2D u = *this; u /= c; return u; } 31 | bool operator==(Vector2D const& v) const { return std::abs(x - v.x) < EPS && std::abs(y - v.y) < EPS; } 32 | bool operator!=(Vector2D const& v) const { return !(*this == v); } 33 | bool operator<(Vector2D const& v) const { return x < v.x || (x == v.x && y < v.y); } 34 | T operator*(Vector2D const& v) const { return x*v.x + y*v.y; } 35 | T operator[](int idx) const { return idx ? y : x; } 36 | 37 | T length2() const { 38 | return sq(x) + sq(y); 39 | } 40 | 41 | double length() const { 42 | return sqrt(length2()); 43 | } 44 | 45 | double atan2_angle() const { 46 | return atan2(y, x); 47 | } 48 | 49 | void normalize() { 50 | double l = length(); 51 | x /= l; 52 | y /= l; 53 | } 54 | 55 | double angle(Vector2D const& v) const { 56 | double angle = v.atan2_angle() - atan2_angle(); 57 | const double PI = acos(-1); 58 | if (angle > PI) 59 | angle -= PI; 60 | if (angle <= -PI) 61 | angle += PI; 62 | return angle; 63 | } 64 | 65 | T x, y; 66 | }; 67 | 68 | template <> 69 | bool Vector2D::operator==(Vector2D const& v) const { 70 | return x == v.x && y == v.y; 71 | } 72 | 73 | template <> 74 | void Vector2D::normalize() { 75 | long long g = std::gcd(x, y); 76 | x /= g; 77 | y /= g; 78 | } 79 | 80 | template 81 | class Point2D { 82 | public: 83 | Point2D(T x=0, T y=0) : x(x), y(y) {} 84 | 85 | Point2D& operator+=(Vector2D const& v) { x += v.x; y += v.y; return *this; } 86 | Point2D operator+(Vector2D const& v) const { Point2D p = *this; p += v; return p; } 87 | Point2D& operator-=(Vector2D const& v) { x -= v.x; y -= v.y; return *this; } 88 | Point2D operator-(Vector2D const& v) const { Point2D p = *this; p -= v; return p; } 89 | Vector2D operator-(Point2D const& p) const { return {x - p.x, y - p.y}; } 90 | bool operator==(Point2D const& p) { return std::abs(x - p.x) < EPS && std::abs(y - p.y) < EPS; } 91 | bool operator!=(Point2D const& p) const { return !(*this == p); } 92 | bool operator<(Point2D const& p) const { return x < p.x || (x == p.x && y < p.y); } 93 | friend std::istream& operator>>(std::istream& is, Point2D& pt) { return is >> pt.x >> pt.y; } 94 | friend std::ostream& operator<<(std::ostream& os, Point2D const& pt) { return os << pt.x << " " << pt.y; } 95 | 96 | T x, y; 97 | }; 98 | 99 | template <> 100 | bool Point2D::operator==(Point2D const& p) { 101 | return x == p.x && y == p.y; 102 | } 103 | 104 | template 105 | class Line2D { 106 | public: 107 | // ax + by + c = 0 108 | Line2D(T a, T b, T c) : a(a), b(b), c(c) {} 109 | // y = kx + d 110 | Line2D(T k, T d) : a(k), b(-1), c(d) {} 111 | // point, point 112 | Line2D(Point2D p, Point2D q) 113 | : a(q.y - p.y), 114 | b(p.x - q.x), 115 | c(p.y * q.x - p.x * q.y) {} 116 | // point + vector 117 | Line2D(Point2D p, Vector2D v) : 118 | a(-v.y), 119 | b(v.x), 120 | c(p.x*v.y - p.y*v.x) {} 121 | 122 | bool parallel(Line2D const& other) const { 123 | return std::abs(det(a, b, other.a, other.b)) < EPS; 124 | } 125 | 126 | Point2D intersect(Line2D const& other) const { 127 | double d = det(a, b, other.a, other.b); 128 | double x = -det(c, b, other.c, other.b) / d; 129 | double y = -det(a, c, other.a, other.c) / d; 130 | return {x, y}; 131 | } 132 | 133 | double distance(Point2D const& p) const { 134 | return std::abs(a*p.x + b*p.y + c) / Vector2D(a, b).length(); 135 | } 136 | 137 | virtual bool contains(Point2D const& p) const { 138 | return std::abs(a*p.x + b*p.y + c) < EPS; 139 | } 140 | 141 | T a, b, c; 142 | }; 143 | 144 | template <> 145 | bool Line2D::parallel(Line2D const& other) const { 146 | return det(a, b, other.a, other.b) == 0; 147 | } 148 | 149 | template <> 150 | bool Line2D::contains(Point2D const& p) const { 151 | return a*p.x + b*p.y + c == 0; 152 | } 153 | 154 | template 155 | class Segment2D : public Line2D { 156 | public: 157 | Segment2D(Point2D p, Point2D q) : Line2D(p, q), p(p), q(q) {} 158 | 159 | bool between_1d(T const x, T const b1, T const b2) const { 160 | return min(b1, b2) <= x && x <= max(b1, b2); 161 | } 162 | 163 | bool contains(Point2D const& pt) const override { 164 | if (!between_1d(pt.x, p.x, q.x) || !between_1d(pt.y, p.y, q.y)) 165 | return false; 166 | return Line2D::contains(pt); 167 | } 168 | 169 | Point2D p, q; 170 | }; 171 | 172 | template 173 | class Circle2D { 174 | public: 175 | Circle2D(Point2D m, T r) : m(m), r(r) {} 176 | Circle2D(T r) : m({0, 0}), r(r) {} 177 | 178 | bool inside(Point2D p) { 179 | return (p - m).length2() < r*r; 180 | } 181 | 182 | std::vector> intersect(Line2D line) { 183 | std::vector> intersections; 184 | T a = line.a; 185 | T b = line.b; 186 | T c = a*m.x + b*m.y + line.c; 187 | double d2 = sq(a) + sq(b); 188 | Point2D closest(-a*c/d2, -b*c/d2); 189 | 190 | T diff = sq(r)*d2 - sq(c); 191 | if (diff > EPS) { 192 | double d = sq(r) - sq(c)/d2; 193 | double factor = sqrt(d / d2); 194 | intersections.push_back(closest + Vector2D{b, -a} * factor); 195 | intersections.push_back(closest + Vector2D{-b, a} * factor); 196 | } else if (std::abs(diff) <= EPS) { 197 | intersections.push_back(closest); 198 | } 199 | 200 | for (auto& p : intersections) 201 | p += Vector2D{m.x, m.y}; 202 | return intersections; 203 | } 204 | 205 | std::vector> intersect(Circle2D other) { 206 | Line2D line(2*(other.m.x - m.x), 207 | 2*(other.m.y - m.y), 208 | sq(other.r) - sq(r) + sq(m.x) + sq(m.y) 209 | - sq(other.m.x) - sq(other.m.y)); 210 | return intersect(line); 211 | } 212 | 213 | Point2D m; 214 | T r; 215 | }; 216 | -------------------------------------------------------------------------------- /Geometry/GrahamScan.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int square(int value) 5 | { 6 | return value * value; 7 | } 8 | 9 | class Point 10 | { 11 | public: 12 | Point(int x, int y) : x(x), y(y) {} 13 | 14 | int dist2(Point const &other) const 15 | { 16 | return square(x - other.x) + square(y - other.y); 17 | } 18 | 19 | // ccw > 0 => counter-clockwise turn 20 | // ccw = 0 => colinear 21 | // ccw < 0 => clockwise turn 22 | static int ccw(Point const &p1, Point const &p2, Point const &p3) 23 | { 24 | return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x); 25 | } 26 | 27 | int x, y; 28 | }; 29 | 30 | std::vector GrahamScan(std::vector points) 31 | { 32 | sort(points.begin(), points.end(), [](auto const &p, auto const &q) { 33 | return std::make_pair(p.y, p.x) < std::make_pair(q.y, q.x); 34 | }); 35 | sort(points.begin() + 1, points.end(), [ref = points[0]](auto const &p, auto const &q) { 36 | int orientation = Point::ccw(ref, p, q); 37 | if (orientation < 0) 38 | return true; 39 | if (orientation == 0) 40 | return ref.dist2(p) < ref.dist2(q); 41 | return false; 42 | }); 43 | 44 | std::vector result; 45 | result.push_back(points[0]); 46 | result.push_back(points[1]); 47 | int sz = 2; 48 | for (int i = 2; i < static_cast(points.size()); i++) { 49 | while (sz > 1 && Point::ccw(result[sz - 2], result[sz - 1], points[i]) >= 0) { 50 | sz--; 51 | result.pop_back(); 52 | } 53 | sz++; 54 | result.push_back(points[i]); 55 | } 56 | 57 | return result; 58 | } 59 | -------------------------------------------------------------------------------- /Geometry/Polygon.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Geometry.h" 3 | 4 | template 5 | double signedArea(std::vector> polygon) { 6 | auto translate = Point{0, 0} - polygon[0]; 7 | for (auto& p : polygon) 8 | p += translate; 9 | 10 | double area = 0; 11 | for (int i = 0; i < (int)polygon.size(); i++) { 12 | auto p = i ? polygon[i-1] : polygon.back(); 13 | auto q = polygon[i]; 14 | area += (double)p.x*q.y - (double)q.x*p.y; 15 | } 16 | return area / 2; 17 | } 18 | 19 | Point centerOfGravity(std::vector> polygon) { 20 | auto translate = Point{0, 0} - polygon[0]; 21 | for (auto& p : polygon) 22 | p += translate; 23 | 24 | double Cx = 0; 25 | double Cy = 0; 26 | for (int i = 0; i < (int)polygon.size(); i++) { 27 | auto p = i ? polygon[i-1] : polygon.back(); 28 | auto q = polygon[i]; 29 | Cx += (p.x + q.x) * (p.x * q.y - p.y * q.x); 30 | Cy += (p.y + q.y) * (p.x * q.y - p.y * q.x); 31 | } 32 | double area = signedArea(polygon); 33 | Point center = {Cx / 6 / area, Cy / 6 / area}; 34 | return center - translate; 35 | } 36 | -------------------------------------------------------------------------------- /Geometry/Rotations.h: -------------------------------------------------------------------------------- 1 | #include "Geometry.h" 2 | #include "../Math/Matrix.h" 3 | 4 | template 5 | Matrix createTranslation2D(Point from, Point to) { 6 | auto vec = to - from; 7 | Matrix translation(3, 3); 8 | for (int i = 0; i < 2; i++) { 9 | translation[i][i] = 1; 10 | translation[i][2] = vec[i]; 11 | } 12 | translation[2][2] = 1; 13 | return translation; 14 | } 15 | 16 | Matrix createRotation2D(double angleRadian) { 17 | Matrix rotation(3, 3); 18 | rotation[0][0] = rotation[1][1] = std::cos(angleRadian); 19 | rotation[0][1] = -std::sin(angleRadian); 20 | rotation[1][0] = -rotation[0][1]; 21 | rotation[2][2] = 1; 22 | return rotation; 23 | } 24 | 25 | template 26 | Point operator*(Matrix const& M, Point p) { 27 | std::vector v = {p.x, p.y, 1}; 28 | auto res = M * v; 29 | return {res[0], res[1]}; 30 | } 31 | -------------------------------------------------------------------------------- /Graphs/BFS.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::vector> adj; 5 | 6 | std::vector bfs(int start) { 7 | int n = adj.size(); 8 | std::vector found(n, false); 9 | std::queue> q; 10 | std::vector dist_to_start(n); 11 | 12 | q.push({start, 0}); 13 | found[start] = true; 14 | 15 | while (!q.empty()) { 16 | auto p = q.front(); 17 | int cur = p.first; 18 | int dist = p.second; 19 | q.pop(); 20 | 21 | dist_to_start[cur] = dist; 22 | 23 | for (auto next : adj[cur]) { 24 | if (!found[next]) { 25 | q.push({next, dist + 1}); 26 | found[next] = true; 27 | } 28 | } 29 | } 30 | 31 | return dist_to_start; 32 | } 33 | -------------------------------------------------------------------------------- /Graphs/Bipartite.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::vector> adj; 4 | std::vector color; 5 | 6 | bool bipartite(int v = 0, int p = -1, int c = 0) 7 | { 8 | if (p == -1) 9 | color.assign(adj.size(), -1); 10 | 11 | if (color[v] >= 0) 12 | return color[v] == c; 13 | color[v] = c; 14 | 15 | for (auto u : adj[v]) { 16 | if (u == p) 17 | continue; 18 | if (!bipartite(u, v, c ^ 1)) 19 | return false; 20 | } 21 | 22 | return true; 23 | } 24 | -------------------------------------------------------------------------------- /Graphs/BlockCutTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Edge { 5 | int to; 6 | int idx; 7 | Edge(int to, int idx) : to(to), idx(idx) {} 8 | }; 9 | 10 | int n, m; 11 | std::vector> adj; 12 | 13 | int timer; 14 | std::vector disc, low; 15 | 16 | std::vector>> bc_components; 17 | std::stack> st; 18 | 19 | void dfs(int v, int p=-1) { 20 | disc[v] = low[v] = ++timer; 21 | int children = 0; 22 | for (Edge e : adj[v]) { 23 | int u = e.to; 24 | if (u == p) 25 | continue; 26 | 27 | if (!disc[u]) { 28 | children++; 29 | st.push({v, u}); 30 | dfs(u, v); 31 | low[v] = std::min(low[v], low[u]); 32 | if ((p != -1 && low[u] >= disc[v]) || 33 | (p == -1 && children > 1)) 34 | { 35 | std::vector> component; 36 | do { 37 | component.push_back(st.top()); 38 | st.pop(); 39 | } while (component.back() != std::make_pair(v, u)); 40 | bc_components.push_back(std::move(component)); 41 | } 42 | } else if (disc[u] < disc[v]) { 43 | st.push({v, u}); 44 | low[v] = std::min(low[v], disc[u]); 45 | } 46 | } 47 | } 48 | 49 | void construct() { 50 | timer = 0; 51 | disc.assign(n, 0); 52 | low.assign(n, 0); 53 | 54 | for (int v = 0; v < n; v++) { 55 | if (!disc[v]) { 56 | dfs(v); 57 | if (!st.empty()) { 58 | std::vector> component; 59 | while (!st.empty()) { 60 | component.push_back(st.top()); 61 | st.pop(); 62 | } 63 | bc_components.push_back(std::move(component)); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Graphs/Bridge_CutPoint.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Edge { 4 | int to; 5 | int idx; 6 | Edge(int to, int idx) : to(to), idx(idx) {} 7 | }; 8 | 9 | int n, m; 10 | std::vector> adj; 11 | 12 | int timer; 13 | std::vector disc, low; 14 | std::vector bridge, cut; 15 | 16 | void dfs(int v, int p=-1) { 17 | disc[v] = low[v] = ++timer; 18 | int children = 0; 19 | for (Edge e : adj[v]) { 20 | int u = e.to; 21 | if (u == p) 22 | continue; 23 | 24 | if (disc[u]) { 25 | low[v] = std::min(low[v], disc[u]); 26 | } else { 27 | children++; 28 | dfs(u, v); 29 | low[v] = std::min(low[v], low[u]); 30 | if (low[u] > disc[v]) 31 | bridge[e.idx] = true; 32 | if ((p != -1 && low[u] >= disc[v]) || 33 | (p == -1 && children > 1)) 34 | cut[v] = true; 35 | } 36 | } 37 | } 38 | 39 | void find() { 40 | timer = 0; 41 | disc.assign(n, 0); 42 | low.assign(n, 0); 43 | bridge.assign(m, false); 44 | cut.assign(n, false); 45 | 46 | for (int v = 0; v < n; v++) { 47 | if (!disc[v]) 48 | dfs(v); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Graphs/CatesianTreeMax.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int CatesianTreeMax(std::vector const& A, std::vector& parent, std::vector>& adj) { 5 | int N = A.size(); 6 | parent.assign(N, -1); 7 | std::stack s; 8 | for (int i = 0; i < N; i++) { 9 | int last = -1; 10 | while (!s.empty() && A[s.top()] <= A[i]) { 11 | last = s.top(); 12 | s.pop(); 13 | } 14 | if (!s.empty()) 15 | parent[i] = s.top(); 16 | if (last >= 0) 17 | parent[last] = i; 18 | s.push(i); 19 | } 20 | 21 | adj.clear(); 22 | adj.resize(N); 23 | int root = -1; 24 | for (int i = 0; i < N; i++) { 25 | if (parent[i] >= 0) 26 | adj[parent[i]].push_back(i); 27 | else 28 | root = i; 29 | } 30 | return root; 31 | } 32 | -------------------------------------------------------------------------------- /Graphs/DFS.h: -------------------------------------------------------------------------------- 1 | int dfs(int v, int p=-1) { 2 | int size = 1; 3 | for (auto u : adj[v]) { 4 | if (u == p) 5 | continue; 6 | size += dfs(u, v); 7 | } 8 | return size; 9 | } 10 | -------------------------------------------------------------------------------- /Graphs/Dijkstra.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::vector dijkstra(std::vector>> const& adj, int v0) { 5 | int n = adj.size(); 6 | std::vector cost(n, -1); 7 | std::priority_queue> pq; 8 | pq.push({0, v0}); 9 | cost[v0] = 0; 10 | while (!pq.empty()) { 11 | auto x = pq.top(); 12 | pq.pop(); 13 | long long c = -x.first; 14 | int v = x.second; 15 | if (c > cost[v]) 16 | continue; 17 | cost[v] = c; 18 | for (auto next : adj[v]) { 19 | if (cost[next.first] == -1 || cost[next.first] > c + next.second) { 20 | cost[next.first] = c + next.second; 21 | pq.push({-(c + next.second), next.first}); 22 | } 23 | } 24 | } 25 | return cost; 26 | } 27 | -------------------------------------------------------------------------------- /Graphs/DivideAndConquer.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::vector> adj; 4 | std::vector subtree_sizes; 5 | std::vector blocked; 6 | 7 | int compute_subtree_sizes(int v, int p) 8 | { 9 | int size = 1; 10 | for (int u : adj[v]) { 11 | if (u != p && !blocked[u]) 12 | size += compute_subtree_sizes(u, v); 13 | } 14 | return subtree_sizes[v] = size; 15 | } 16 | 17 | long long solve(int v) 18 | { 19 | int size = compute_subtree_sizes(v, v); 20 | bool pushed = true; 21 | int p = -1; 22 | while (pushed) { 23 | pushed = false; 24 | for (int u : adj[v]) { 25 | if (u != p && !blocked[u] && subtree_sizes[u] > size / 2) { 26 | pushed = true; 27 | p = v; 28 | v = u; 29 | break; 30 | } 31 | } 32 | } 33 | 34 | long long result = 0; 35 | // compute result for node v and all unblocked children 36 | 37 | blocked[v] = true; 38 | for (int u : adj[v]) { 39 | if (!blocked[u]) 40 | result += solve(u); 41 | } 42 | 43 | return result; 44 | } 45 | -------------------------------------------------------------------------------- /Graphs/EdmondKarp.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | class EdmondKarp 7 | { 8 | public: 9 | EdmondKarp(int n, std::vector> capacity) 10 | : n(n), capacity(capacity) {} 11 | 12 | int maxflow(int s, int t) { 13 | adj.resize(n); 14 | for (int i = 0; i < n; i++) { 15 | for (int j = 0; j < n; j++) { 16 | if (capacity[i][j] || capacity[j][i]) 17 | adj[i].push_back(j); 18 | } 19 | } 20 | 21 | int flow = 0; 22 | 23 | std::vector parent(n); 24 | int new_flow; 25 | 26 | while ((new_flow = bfs(s, t, parent))) { 27 | flow += new_flow; 28 | int node = t; 29 | while (node != s) { 30 | int prev = parent[node]; 31 | capacity[prev][node] -= new_flow; 32 | capacity[node][prev] += new_flow; 33 | node = prev; 34 | } 35 | } 36 | 37 | return flow; 38 | } 39 | 40 | int bfs(int s, int t, std::vector& parent) { 41 | fill(parent.begin(), parent.end(), -1); 42 | parent[s] = -2; 43 | std::queue> q; 44 | q.push({s, std::numeric_limits::max()}); 45 | 46 | while (!q.empty()) { 47 | int node, flow; 48 | std::tie(node, flow) = q.front(); 49 | q.pop(); 50 | 51 | for (auto next : adj[node]) { 52 | if (parent[next] == -1 && capacity[node][next]) { 53 | parent[next] = node; 54 | int new_flow = std::min(flow, capacity[node][next]); 55 | if (next == t) 56 | return new_flow; 57 | q.push({next, new_flow}); 58 | } 59 | } 60 | } 61 | 62 | return 0; 63 | } 64 | 65 | int n; 66 | std::vector> capacity; 67 | std::vector> adj; 68 | }; 69 | -------------------------------------------------------------------------------- /Graphs/FindOddCycle.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Edge { 4 | int from, to, idx; 5 | }; 6 | 7 | std::vector> adj; 8 | 9 | std::vector color; 10 | std::vector odd_cycle; 11 | std::vector pre; 12 | 13 | bool findOddCycle(Edge e = {-1, 0, -1}, int c = 0) 14 | { 15 | int v = e.to; 16 | int p = e.from; 17 | 18 | if (p == -1) { 19 | color.assign(adj.size(), -1); 20 | pre.resize(adj.size()); 21 | } 22 | 23 | if (color[v] >= 0) { 24 | // even cycle 25 | if (color[v] == c) 26 | return false; 27 | 28 | // odd cycle 29 | odd_cycle.push_back(e); 30 | int cur = p; 31 | do { 32 | odd_cycle.push_back(pre[cur]); 33 | cur = pre[cur].to; 34 | } while (cur != v); 35 | return true; 36 | } 37 | 38 | color[v] = c; 39 | pre[v] = e; 40 | 41 | for (auto f : adj[v]) { 42 | if (f.idx == e.idx) 43 | continue; 44 | if (findOddCycle(f, c ^ 1)) 45 | return true; 46 | } 47 | 48 | return false; 49 | } 50 | -------------------------------------------------------------------------------- /Graphs/Floyd-Warshall.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void Floyd_Warshall(std::vector> &cost) { 5 | int n = cost.size(); 6 | 7 | for (int i = 0; i < n; i++) { 8 | cost[i][i] = 0; 9 | } 10 | 11 | for (int k = 0; k < n; k++) { 12 | for (int i = 0; i < n; i++) { 13 | for (int j = 0; j < n; j++) { 14 | cost[i][j] = std::min(cost[i][j], cost[i][k] + cost[k][j]); 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Graphs/HLD.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class SegmentTree { 4 | public: 5 | SegmentTree(int count) { 6 | n = count; 7 | data.assign(2 * n, 0); 8 | } 9 | 10 | int maximum(int left, int right) { // interval [left, right) 11 | int ret = 0; 12 | left += n; 13 | right += n; 14 | 15 | while (left < right) { 16 | if (left & 1) 17 | ret = std::max(ret, data[left++]); 18 | if (right & 1) 19 | ret = std::max(ret, data[--right]); 20 | left >>= 1; 21 | right >>= 1; 22 | } 23 | return ret; 24 | } 25 | 26 | void update(int idx, int val) { 27 | idx += n; 28 | data[idx] = val; 29 | 30 | while (idx > 1) { 31 | idx /= 2; 32 | data[idx] = std::max(data[idx * 2], data[idx * 2 + 1]); 33 | } 34 | } 35 | 36 | private: 37 | int n; 38 | std::vector data; 39 | }; 40 | 41 | enum ValueType {NodeValues=0, EdgeValues=1}; 42 | 43 | /** 44 | * Heavy-Light decomposition 45 | * 46 | * Either every edge has a value, or every node has a value. 47 | * In the node version, the value of the node `v` is simply stored at `pos[v]`. 48 | * In the edge version, the value of the edge `u-v` is stored at `pos[v]`, 49 | * where `v` is the child of `u`. Be careful to not include the edge from the LCA to it's parent. 50 | * 51 | * `head[v]` will be the start of the current path (so the highest ancestor of `v`). 52 | */ 53 | template 54 | class HLD { 55 | public: 56 | HLD(std::vector> const& adj, int root = 0) 57 | : adj(adj), n(adj.size()), segtree(n) { 58 | parent = std::vector(n); 59 | depth = std::vector(n); 60 | heavy = std::vector(n, -1); 61 | head = std::vector(n); 62 | pos = std::vector(n); 63 | cur_pos = 0; 64 | 65 | dfs(root); 66 | decompose(root, root); 67 | 68 | segtree = SegmentTree(n); 69 | } 70 | 71 | template::type = 0> 72 | void update_node(int v, int val) { 73 | segtree.update(pos[v], val); 74 | } 75 | 76 | template::type = 0> 77 | void update_edge(int u, int v, int val) { 78 | if (depth[u] > depth[v]) 79 | std::swap(u, v); 80 | segtree.update(pos[v], val); 81 | } 82 | 83 | int dfs(int v, int p = -1, int d = 0) { 84 | parent[v] = p; 85 | depth[v] = d; 86 | int size = 1; 87 | int max_child_size = 0; 88 | for (int u : adj[v]) { 89 | if (u != parent[v]) { 90 | int u_size = dfs(u, v, d + 1); 91 | size += u_size; 92 | if (u_size > max_child_size) { 93 | max_child_size = u_size; 94 | heavy[v] = u; 95 | } 96 | } 97 | } 98 | return size; 99 | } 100 | 101 | void decompose(int v, int h) { 102 | head[v] = h; 103 | pos[v] = cur_pos++; 104 | if (heavy[v] != -1) 105 | decompose(heavy[v], h); 106 | for (int u : adj[v]) { 107 | if (u != parent[v] && u != heavy[v]) 108 | decompose(u, u); 109 | } 110 | } 111 | 112 | int query_max(int a, int b) { 113 | int res = 0; 114 | for (; head[a] != head[b]; b = parent[head[b]]) { 115 | if (depth[head[a]] > depth[head[b]]) 116 | std::swap(a, b); 117 | int cur_heavy_path = segtree.maximum(pos[head[b]], pos[b] + 1); 118 | res = std::max(res, cur_heavy_path); 119 | } 120 | 121 | if (depth[a] > depth[b]) 122 | std::swap(a, b); 123 | int last_heavy_path = segtree.maximum(pos[a] + VT, pos[b] + 1); 124 | res = std::max(res, last_heavy_path); 125 | return res; 126 | } 127 | 128 | private: 129 | std::vector> const& adj; 130 | int n; 131 | 132 | public: 133 | SegmentTree segtree; 134 | int cur_pos; 135 | std::vector parent, depth, heavy, head, pos; 136 | }; 137 | -------------------------------------------------------------------------------- /Graphs/HopcroftKarp.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // maximal matching in O(sqrt(V) * E) 6 | class HopcroftKarp 7 | { 8 | public: 9 | HopcroftKarp(int n1, int n2) : n1(n1), n2(n2) { 10 | adj.resize(n1 + 1); 11 | match.assign(n1 + 1, 0); 12 | matched.assign(n2 + 1, 0); 13 | dist.resize(n1 + 1); 14 | } 15 | 16 | // nodes are 1-indexed 17 | void add(int u, int v) { 18 | adj[u].push_back(v); 19 | } 20 | 21 | int maximalMatching() { 22 | int matchings = 0; 23 | while (bfs()) { 24 | for (int u = 1; u <= n1; u++) { 25 | if (!match[u]) { 26 | if (dfs(u)) 27 | matchings++; 28 | } 29 | } 30 | } 31 | return matchings; 32 | } 33 | 34 | private: 35 | bool bfs() { 36 | std::queue q; 37 | dist[0] = INF; 38 | for (int u = 1; u <= n1; u++) { 39 | if (!match[u]) { 40 | dist[u] = 0; 41 | q.push(u); 42 | } else { 43 | dist[u] = INF; 44 | } 45 | } 46 | 47 | while (!q.empty()) { 48 | int u = q.front(); 49 | q.pop(); 50 | if (dist[u] < dist[0]) { 51 | for (int v : adj[u]) { 52 | if (dist[matched[v]] == INF) { 53 | dist[matched[v]] = dist[u] + 1; 54 | q.push(matched[v]); 55 | } 56 | } 57 | 58 | } 59 | } 60 | return dist[0] != INF; 61 | } 62 | 63 | bool dfs(int u) { 64 | if (u == 0) 65 | return true; 66 | 67 | for (int v : adj[u]) { 68 | if (dist[matched[v]] == dist[u] + 1) { 69 | if (dfs(matched[v])) { 70 | matched[v] = u; 71 | match[u] = v; 72 | return true; 73 | } 74 | } 75 | } 76 | dist[u] = INF; 77 | return false; 78 | } 79 | 80 | static const int INF = std::numeric_limits::max(); 81 | int n1, n2; 82 | std::vector dist; 83 | std::vector> adj; 84 | public: 85 | std::vector match, matched; 86 | }; 87 | -------------------------------------------------------------------------------- /Graphs/Kruskal.h: -------------------------------------------------------------------------------- 1 | #include "UnionFind.h" 2 | 3 | struct Edge { 4 | int u, v, w; 5 | bool used = false; 6 | }; 7 | 8 | int MST_Kruskal(std::vector edges, int nodes) 9 | { 10 | sort(edges.begin(), edges.end(), 11 | [](Edge const &e, Edge const &f) { return e.w < f.w; }); 12 | 13 | UnionFind uf(nodes); 14 | int cost = 0; 15 | for (Edge &e : edges) { 16 | if (!uf.sameUnion(e.u, e.v)) { 17 | uf.Union(e.u, e.v); 18 | e.used = true; 19 | cost += e.w; 20 | } 21 | } 22 | return cost; 23 | } 24 | -------------------------------------------------------------------------------- /Graphs/LCA.h: -------------------------------------------------------------------------------- 1 | #include "../RangeQuery/SparseTable.h" 2 | 3 | class LCA 4 | { 5 | public: 6 | LCA(std::vector> adj) : adj(adj) { 7 | int nodes = adj.size(); 8 | first_encounter.resize(nodes); 9 | dfs_euler_tour(0, -1); 10 | st = new SparseTable(euler_tour); 11 | } 12 | 13 | ~LCA() { 14 | delete st; 15 | } 16 | 17 | int query(int u, int v) { 18 | int fe1 = first_encounter[u]; 19 | int fe2 = first_encounter[v]; 20 | if (fe1 > fe2) 21 | std::swap(fe1, fe2); 22 | int LCA_new_index = st->minimum(fe1, fe2+1); 23 | int LCA_old_index = new_to_old[LCA_new_index]; 24 | return LCA_old_index; 25 | } 26 | 27 | private: 28 | void dfs_euler_tour(int v, int p) { 29 | int new_index = new_to_old.size(); 30 | new_to_old.push_back(v); 31 | first_encounter[v] = euler_tour.size(); 32 | euler_tour.push_back(new_index); 33 | 34 | for (int u : adj[v]) { 35 | if (u == p) 36 | continue; 37 | 38 | dfs_euler_tour(u, v); 39 | euler_tour.push_back(new_index); 40 | } 41 | } 42 | 43 | std::vector> adj; 44 | std::vector euler_tour; 45 | std::vector first_encounter; 46 | std::vector new_to_old; 47 | SparseTable* st; 48 | }; 49 | -------------------------------------------------------------------------------- /Graphs/LCA_Binary_Lifting.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class LCA_Binary_Lifting 4 | { 5 | public: 6 | LCA_Binary_Lifting(std::vector> adj, int root) 7 | : root(root), adj(adj) 8 | { 9 | int n = adj.size(); 10 | 11 | log = 1; 12 | while ((1 << log) < n) 13 | log++; 14 | parents.assign(log, std::vector(n, -1)); 15 | 16 | height.resize(n); 17 | dfs(root, -1, 0); 18 | 19 | for (int l = 1; l < log; l++) { 20 | for (int v = 0; v < n; v++) { 21 | if (parents[l - 1][v] >= 0) 22 | parents[l][v] = parents[l - 1][parents[l - 1][v]]; 23 | } 24 | } 25 | } 26 | 27 | int find_parent(int v, int up) 28 | { 29 | for (int l = 0; v != -1 && up > 0; l++, up >>= 1) { 30 | if (up & 1) { 31 | v = parents[l][v]; 32 | } 33 | } 34 | return v; 35 | } 36 | 37 | int LCA(int u, int v) 38 | { 39 | if (height[u] < height[v]) 40 | std::swap(u, v); 41 | u = find_parent(u, height[u] - height[v]); 42 | 43 | for (int l = log - 1; l >= 0; l--) { 44 | if (parents[l][u] != parents[l][v]) { 45 | u = parents[l][u]; 46 | v = parents[l][v]; 47 | } 48 | } 49 | 50 | if (u == v) 51 | return u; 52 | else 53 | return parents[0][u]; 54 | } 55 | 56 | private: 57 | void dfs(int v, int p, int h) 58 | { 59 | parents[0][v] = p; 60 | height[v] = h; 61 | for (int u : adj[v]) { 62 | if (u != p) 63 | dfs(u, v, h + 1); 64 | } 65 | } 66 | 67 | int log; 68 | int root; 69 | std::vector> adj, parents; 70 | std::vector height; 71 | }; 72 | -------------------------------------------------------------------------------- /Graphs/LCA_Farach_Colton_Bender.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int n; 4 | std::vector> adj; 5 | 6 | int block_size, block_cnt; 7 | std::vector first_visit; 8 | std::vector euler_tour; 9 | std::vector height; 10 | std::vector log_2; 11 | std::vector> st; 12 | std::vector>> blocks; 13 | std::vector block_mask; 14 | 15 | void dfs(int v, int p, int h) { 16 | first_visit[v] = euler_tour.size(); 17 | euler_tour.push_back(v); 18 | height[v] = h; 19 | 20 | for (int u : adj[v]) { 21 | if (u == p) 22 | continue; 23 | dfs(u, v, h + 1); 24 | euler_tour.push_back(v); 25 | } 26 | } 27 | 28 | int min_by_h(int i, int j) { 29 | return height[euler_tour[i]] < height[euler_tour[j]] ? i : j; 30 | } 31 | 32 | void precompute_lca(int root) { 33 | // get euler tour & indices of first occurences 34 | first_visit.assign(n, -1); 35 | height.assign(n, 0); 36 | euler_tour.reserve(2 * n); 37 | dfs(root, -1, 0); 38 | 39 | // precompute all log values 40 | int m = euler_tour.size(); 41 | log_2.reserve(m + 1); 42 | log_2.push_back(-1); 43 | for (int i = 1; i <= m; i++) 44 | log_2.push_back(log_2[i / 2] + 1); 45 | 46 | block_size = std::max(1, log_2[m] / 2); 47 | block_cnt = (m + block_size - 1) / block_size; 48 | 49 | // precompute minimum of each block and build sparse table 50 | st.assign(block_cnt, std::vector(log_2[block_cnt] + 1)); 51 | for (int i = 0, j = 0, b = 0; i < m; i++, j++) { 52 | if (j == block_size) 53 | j = 0, b++; 54 | if (j == 0 || min_by_h(i, st[b][0]) == i) 55 | st[b][0] = i; 56 | } 57 | for (int l = 1; l <= log_2[block_cnt]; l++) { 58 | for (int i = 0; i < block_cnt; i++) { 59 | int ni = i + (1 << (l - 1)); 60 | if (ni >= block_cnt) 61 | st[i][l] = st[i][l-1]; 62 | else 63 | st[i][l] = min_by_h(st[i][l-1], st[ni][l-1]); 64 | } 65 | } 66 | 67 | // precompute mask for each block 68 | block_mask.assign(block_cnt, 0); 69 | for (int i = 0, j = 0, b = 0; i < m; i++, j++) { 70 | if (j == block_size) 71 | j = 0, b++; 72 | if (j > 0 && (i >= m || min_by_h(i - 1, i) == i - 1)) 73 | block_mask[b] += 1 << (j - 1); 74 | } 75 | 76 | // precompute RMQ for each unique block 77 | int possibilities = 1 << (block_size - 1); 78 | blocks.resize(possibilities); 79 | for (int b = 0; b < block_cnt; b++) { 80 | int mask = block_mask[b]; 81 | if (!blocks[mask].empty()) 82 | continue; 83 | blocks[mask].assign(block_size, std::vector(block_size)); 84 | for (int l = 0; l < block_size; l++) { 85 | blocks[mask][l][l] = l; 86 | for (int r = l + 1; r < block_size; r++) { 87 | blocks[mask][l][r] = blocks[mask][l][r - 1]; 88 | if (b * block_size + r < m) 89 | blocks[mask][l][r] = min_by_h(b * block_size + blocks[mask][l][r], 90 | b * block_size + r) - b * block_size; 91 | } 92 | } 93 | } 94 | } 95 | 96 | int lca_in_block(int b, int l, int r) { 97 | return blocks[block_mask[b]][l][r] + b * block_size; 98 | } 99 | 100 | int lca(int v, int u) { 101 | int l = first_visit[v]; 102 | int r = first_visit[u]; 103 | if (l > r) 104 | std::swap(l, r); 105 | int bl = l / block_size; 106 | int br = r / block_size; 107 | if (bl == br) 108 | return euler_tour[lca_in_block(bl, l % block_size, r % block_size)]; 109 | int ans1 = lca_in_block(bl, l % block_size, block_size - 1); 110 | int ans2 = lca_in_block(br, 0, r % block_size); 111 | int ans = min_by_h(ans1, ans2); 112 | if (bl + 1 < br) { 113 | int l = log_2[br - bl - 1]; 114 | int ans3 = st[bl+1][l]; 115 | int ans4 = st[br - (1 << l)][l]; 116 | ans = min_by_h(ans, min_by_h(ans3, ans4)); 117 | } 118 | return euler_tour[ans]; 119 | } 120 | -------------------------------------------------------------------------------- /Graphs/MinCostMaxFlow.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct Edge { 7 | int from, to, cost, capacity; 8 | Edge(int from=-1, int to=-1, int cost=0, int capacity=0) 9 | : from(from), to(to), cost(cost), capacity(capacity) { 10 | } 11 | }; 12 | 13 | std::pair> BellmanFord(std::vector const& edges, int s, int n) { 14 | int INF = std::numeric_limits::max(); 15 | std::vector d(n, INF); 16 | d[s] = 0; 17 | 18 | bool improved = true; 19 | for (int i = 0; i < n && improved; ++i) { 20 | improved = false; 21 | for (Edge const& e : edges) { 22 | if (e.capacity > 0 && d[e.from] < INF && d[e.from] + e.cost < d[e.to]) { 23 | d[e.to] = d[e.from] + e.cost; 24 | improved = true; 25 | } 26 | } 27 | } 28 | return {improved, d}; // true if negative cycle 29 | } 30 | 31 | class MinCostMaxFlow { 32 | public: 33 | std::pair solve(std::vector const& edges, int source, int sink, int n) { 34 | int m = (int)edges.size(); 35 | std::vector directed_edges(2 * m); 36 | capacity.assign(n, std::vector(n, 0)); 37 | cost.assign(n, std::vector(n, 0)); 38 | adj.resize(n); 39 | for (int i = 0; i < m; i++) { 40 | Edge e = edges[i]; 41 | directed_edges[i] = e; 42 | directed_edges[i + m] = Edge(e.to, e.from, -e.cost, 0); 43 | capacity[e.from][e.to] = e.capacity; 44 | cost[e.from][e.to] = e.cost; 45 | cost[e.to][e.from] = -e.cost; 46 | adj[e.from].push_back(e.to); 47 | adj[e.to].push_back(e.from); 48 | } 49 | 50 | auto [negative_cycle, distances] = BellmanFord(directed_edges, source, n); 51 | assert(!negative_cycle); 52 | potential = distances; 53 | 54 | int flow = 0; 55 | int total_cost = 0; 56 | while (true) { 57 | auto [distances, parent] = dijkstra(source); 58 | if (parent[sink] == -1) 59 | break; 60 | 61 | // fix potentials 62 | for (int i = 0; i < n; i++) { 63 | if (distances[i] < std::numeric_limits::max()) 64 | potential[i] += distances[i]; 65 | } 66 | 67 | // augment path 68 | int cur_flow = std::numeric_limits::max(); 69 | int cur = sink; 70 | while (cur != source) { 71 | int prev = parent[cur]; 72 | cur_flow = std::min(cur_flow, capacity[prev][cur]); 73 | cur = prev; 74 | } 75 | cur = sink; 76 | flow += cur_flow; 77 | while (cur != source) { 78 | int prev = parent[cur]; 79 | total_cost += cur_flow * cost[prev][cur]; 80 | capacity[prev][cur] -= cur_flow; 81 | capacity[cur][prev] += cur_flow; 82 | cur = prev; 83 | } 84 | } 85 | 86 | return {flow, total_cost}; 87 | } 88 | 89 | std::pair, std::vector> dijkstra(int v0) { 90 | int n = adj.size(); 91 | int INF = std::numeric_limits::max(); 92 | std::vector distance(n, INF), parent(n, -1); 93 | std::priority_queue> pq; 94 | pq.push({0, v0}); 95 | distance[v0] = 0; 96 | while (!pq.empty()) { 97 | auto x = pq.top(); 98 | pq.pop(); 99 | long long dist = -x.first; 100 | int v = x.second; 101 | if (dist > distance[v]) 102 | continue; 103 | for (auto u : adj[v]) { 104 | if (capacity[v][u] == 0) 105 | continue; 106 | int new_cost = cost[v][u] + potential[v]- potential[u]; 107 | if (dist + new_cost < distance[u]) { 108 | distance[u] = dist + new_cost; 109 | parent[u] = v; 110 | pq.push({-distance[u], u}); 111 | } 112 | } 113 | } 114 | return {distance, parent}; 115 | } 116 | 117 | private: 118 | std::vector potential; 119 | std::vector> capacity, cost; 120 | std::vector> adj; 121 | }; 122 | -------------------------------------------------------------------------------- /Graphs/MinCostMaxFlowMultipleEdges.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct Edge { 7 | int from, to, cost, capacity; 8 | Edge(int from=-1, int to=-1, int cost=0, int capacity=0) 9 | : from(from), to(to), cost(cost), capacity(capacity) { 10 | } 11 | }; 12 | 13 | std::pair> BellmanFord(std::vector const& edges, int s, int n) { 14 | int INF = std::numeric_limits::max(); 15 | std::vector d(n, INF); 16 | d[s] = 0; 17 | 18 | bool improved = true; 19 | for (int i = 0; i < n && improved; ++i) { 20 | improved = false; 21 | for (Edge const& e : edges) { 22 | if (e.capacity > 0 && d[e.from] < INF && d[e.from] + e.cost < d[e.to]) { 23 | d[e.to] = d[e.from] + e.cost; 24 | improved = true; 25 | } 26 | } 27 | } 28 | return {improved, d}; // true if negative cycle 29 | } 30 | 31 | class MinCostMaxFlow { 32 | public: 33 | std::pair solve(std::vector const& edges, int source, int sink, int n) { 34 | int m = (int)edges.size(); 35 | directed_edges.resize(2 * m); 36 | adj.resize(n); 37 | for (int i = 0; i < m; i++) { 38 | Edge e = edges[i]; 39 | directed_edges[2*i] = e; 40 | directed_edges[2*i+1] = Edge(e.to, e.from, -e.cost, 0); 41 | adj[e.from].push_back(2*i); 42 | adj[e.to].push_back(2*i+1); 43 | } 44 | 45 | auto [negative_cycle, distances] = BellmanFord(directed_edges, source, n); 46 | assert(!negative_cycle); 47 | potential = distances; 48 | 49 | int flow = 0; 50 | int total_cost = 0; 51 | while (true) { 52 | auto [distances, prev_edge] = dijkstra(source); 53 | if (prev_edge[sink] == -1) 54 | break; 55 | 56 | // fix potentials 57 | for (int i = 0; i < n; i++) { 58 | if (distances[i] < std::numeric_limits::max()) 59 | potential[i] += distances[i]; 60 | } 61 | 62 | // augment path 63 | int cur_flow = std::numeric_limits::max(); 64 | int cur = sink; 65 | while (cur != source) { 66 | int prev_edge_idx = prev_edge[cur]; 67 | Edge& prev_edge = directed_edges[prev_edge_idx]; 68 | cur_flow = std::min(cur_flow, prev_edge.capacity); 69 | cur = prev_edge.from; 70 | } 71 | cur = sink; 72 | flow += cur_flow; 73 | while (cur != source) { 74 | int prev_edge_idx = prev_edge[cur]; 75 | Edge& prev_edge = directed_edges[prev_edge_idx]; 76 | Edge& prev_edge_rev = directed_edges[prev_edge_idx ^ 1]; 77 | total_cost += cur_flow * prev_edge.cost; 78 | prev_edge.capacity -= cur_flow; 79 | prev_edge_rev.capacity += cur_flow; 80 | cur = prev_edge.from; 81 | } 82 | } 83 | 84 | return {flow, total_cost}; 85 | } 86 | 87 | std::pair, std::vector> dijkstra(int v0) { 88 | int n = adj.size(); 89 | int INF = std::numeric_limits::max(); 90 | std::vector distance(n, INF), prev_edge(n, -1); 91 | std::priority_queue> pq; 92 | pq.push({0, v0}); 93 | distance[v0] = 0; 94 | while (!pq.empty()) { 95 | auto x = pq.top(); 96 | pq.pop(); 97 | long long dist = -x.first; 98 | int v = x.second; 99 | if (dist > distance[v]) 100 | continue; 101 | for (auto e_idx : adj[v]) { 102 | Edge& e = directed_edges[e_idx]; 103 | if (e.capacity == 0) 104 | continue; 105 | int new_cost = e.cost + potential[v]- potential[e.to]; 106 | if (dist + new_cost < distance[e.to]) { 107 | distance[e.to] = dist + new_cost; 108 | prev_edge[e.to] = e_idx; 109 | pq.push({-distance[e.to], e.to}); 110 | } 111 | } 112 | } 113 | return {distance, prev_edge}; 114 | } 115 | 116 | private: 117 | std::vector potential; 118 | std::vector> adj; 119 | std::vector directed_edges; 120 | }; 121 | -------------------------------------------------------------------------------- /Graphs/SCC.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class SCC 5 | { 6 | public: 7 | SCC(int n) : n(n) { 8 | adj.resize(n); 9 | adj_t.resize(n); 10 | } 11 | 12 | void add_edge(int u, int v) 13 | { 14 | adj[u].push_back(v); 15 | adj_t[v].push_back(u); 16 | } 17 | 18 | int solve() 19 | { 20 | visited.assign(n, false); 21 | for (int i = 0; i < n; ++i) { 22 | if (!visited[i]) 23 | dfs1(i); 24 | } 25 | visited.assign(n, false); 26 | reverse(order.begin(), order.end()); 27 | components.clear(); 28 | component.resize(n); 29 | int c = 0; 30 | for (int i : order) { 31 | if (!visited[i]) { 32 | components.push_back({}); 33 | dfs2(i, c); 34 | c++; 35 | } 36 | } 37 | 38 | adj_condensation.resize(c); 39 | for (int v = 0; v < n; v++) { 40 | for (int u : adj[v]) { 41 | if (component[v] != component[u]) 42 | adj_condensation[component[v]].push_back(component[u]); 43 | } 44 | } 45 | for (int v = 0; v < c; v++) { 46 | auto& vec = adj_condensation[v]; 47 | sort(vec.begin(), vec.end()); 48 | vec.resize(unique(vec.begin(), vec.end()) - vec.begin()); 49 | } 50 | 51 | return c; 52 | } 53 | 54 | void dfs1(int v) 55 | { 56 | visited[v] = true; 57 | for (int u : adj[v]) { 58 | if (!visited[u]) 59 | dfs1(u); 60 | } 61 | order.push_back(v); 62 | } 63 | 64 | void dfs2(int v, int c) 65 | { 66 | visited[v] = true; 67 | components.back().push_back(v); 68 | component[v] = c; 69 | for (int u : adj_t[v]) { 70 | if (!visited[u]) 71 | dfs2(u, c); 72 | } 73 | } 74 | 75 | int n; 76 | std::vector> adj, adj_t, components, adj_condensation; 77 | std::vector visited; 78 | std::vector order, component; 79 | }; 80 | -------------------------------------------------------------------------------- /Graphs/TopologicalSort.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace TopologicalSort { 5 | using AdjacencyList = std::vector>; 6 | std::vector visited; 7 | std::vector order; 8 | 9 | void dfs(int v, AdjacencyList const& adj) { 10 | visited[v] = true; 11 | for (int u : adj[v]) { 12 | if (!visited[u]) 13 | dfs(u, adj); 14 | } 15 | order.push_back(v); 16 | } 17 | 18 | std::vector sort(AdjacencyList const& adj) { 19 | int n = adj.size(); 20 | order.clear(); 21 | order.reserve(n); 22 | visited.assign(n, false); 23 | for (int v = 0; v < n; v++) { 24 | if (!visited[v]) 25 | dfs(v, adj); 26 | } 27 | std::reverse(order.begin(), order.end()); 28 | return order; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Graphs/TwoSAT.h: -------------------------------------------------------------------------------- 1 | #include "SCC.h" 2 | 3 | class TwoSAT 4 | { 5 | public: 6 | TwoSAT(int n) : n(n), scc(2 * n) {} 7 | 8 | void add_clause(int var1, bool b1, int var2, bool b2) 9 | { 10 | scc.add_edge(var1 * 2 + b1, var2 * 2 + !b2); 11 | scc.add_edge(var2 * 2 + b2, var1 * 2 + !b1); 12 | } 13 | 14 | bool solve() 15 | { 16 | scc.solve(); 17 | 18 | assignment.assign(n, false); 19 | for (int i = 0; i < n; i++) { 20 | if (scc.component[2 * i] == scc.component[2 * i + 1]) 21 | return false; 22 | assignment[i] = scc.component[2 * i] > scc.component[2 * i + 1]; 23 | } 24 | return true; 25 | } 26 | 27 | int n; 28 | SCC scc; 29 | std::vector assignment; 30 | }; 31 | -------------------------------------------------------------------------------- /Graphs/UnionFind.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class UnionFind 5 | { 6 | public: 7 | UnionFind(int n) 8 | { 9 | p.resize(n); 10 | std::iota(p.begin(), p.end(), 0); 11 | rank.assign(n, 0); 12 | } 13 | 14 | int Find(int x) { return x == p[x] ? x : p[x] = Find(p[x]); } 15 | 16 | bool Union(int x, int y) 17 | { 18 | int xRoot = Find(x); 19 | int yRoot = Find(y); 20 | 21 | if (xRoot == yRoot) 22 | return false; 23 | 24 | if (rank[xRoot] < rank[yRoot]) { 25 | p[xRoot] = yRoot; 26 | } else if (rank[xRoot] > rank[yRoot]) { 27 | p[yRoot] = xRoot; 28 | } else { 29 | p[yRoot] = xRoot; 30 | rank[xRoot]++; 31 | } 32 | return true; 33 | } 34 | 35 | bool sameUnion(int x, int y) { return Find(x) == Find(y); } 36 | 37 | private: 38 | std::vector p, rank; 39 | }; 40 | -------------------------------------------------------------------------------- /Graphs/UnionFindWithSets.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class UnionFind 5 | { 6 | public: 7 | UnionFind(int n) 8 | { 9 | p.resize(n); 10 | std::iota(p.begin(), p.end(), 0); 11 | sets.resize(n); 12 | for (int i = 0; i < n; i++) 13 | sets[i].push_back(i); 14 | } 15 | 16 | int Find(int x) { return p[x]; } 17 | 18 | bool Union(int x, int y) 19 | { 20 | int xRoot = Find(x); 21 | int yRoot = Find(y); 22 | 23 | if (xRoot == yRoot) 24 | return false; 25 | 26 | if (sets[xRoot].size() < sets[yRoot].size()) 27 | swap(xRoot, yRoot); 28 | 29 | for (int elem : sets[yRoot]) { 30 | p[elem] = xRoot; 31 | sets[xRoot].push_back(elem); 32 | } 33 | sets[yRoot].clear(); 34 | 35 | return true; 36 | } 37 | 38 | bool sameUnion(int x, int y) { return Find(x) == Find(y); } 39 | 40 | private: 41 | std::vector p; 42 | std::vector> sets; 43 | }; 44 | -------------------------------------------------------------------------------- /Graphs/lca.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class RMQ 7 | { 8 | public: 9 | RMQ(vector v) { 10 | log_table.assign(v.size() + 1, 0); 11 | for (int i = 2; i < log_table.size(); i++) 12 | log_table[i] = log_table[i/2] + 1; 13 | 14 | sparse_table.assign(log_table.back() + 1, vector(v.size())); 15 | sparse_table[0] = v; 16 | for (int row = 1; row < sparse_table.size(); row++) { 17 | for (int i = 0; i + (1 << row) <= v.size(); i++) { 18 | sparse_table[row][i] = min(sparse_table[row-1][i], sparse_table[row-1][i+(1<<(row-1))]); 19 | } 20 | } 21 | } 22 | 23 | int minimum(int l, int r) { 24 | int log = log_table[r - l]; 25 | return min(sparse_table[log][l], sparse_table[log][r - (1 << log)]); 26 | } 27 | 28 | private: 29 | vector log_table; 30 | vector> sparse_table; 31 | }; 32 | 33 | vector> adj; 34 | vector euler_tour; 35 | vector first_encounter; 36 | vector new_to_old; 37 | 38 | void dfs_euler_tour(int v, int p) { 39 | int new_index = new_to_old.size(); 40 | new_to_old.push_back(v); 41 | first_encounter[v] = euler_tour.size(); 42 | euler_tour.push_back(new_index); 43 | 44 | for (int u : adj[v]) { 45 | if (u == p) 46 | continue; 47 | 48 | dfs_euler_tour(u, v); 49 | euler_tour.push_back(new_index); 50 | } 51 | } 52 | 53 | int main() { 54 | int nodes = 10; 55 | vector> edges = {{0, 5}, {5, 7}, {7, 2}, {5, 1}, {1, 3}, {1, 6}, {5, 8}, {0, 9}, {9, 4}}; 56 | 57 | adj.resize(nodes); 58 | for (auto edge : edges) { 59 | adj[edge.first].push_back(edge.second); 60 | adj[edge.second].push_back(edge.first); 61 | } 62 | 63 | first_encounter.resize(nodes); 64 | dfs_euler_tour(0, -1); 65 | RMQ rmq(euler_tour); 66 | 67 | int u, v; 68 | cin >> u >> v; 69 | int fe1 = first_encounter[u]; 70 | int fe2 = first_encounter[v]; 71 | if (fe1 > fe2) 72 | swap(fe1, fe2); 73 | int LCA_new_index = rmq.minimum(fe1, fe2+1); 74 | int LCA_old_index = new_to_old[LCA_new_index]; 75 | cout << "LCA_new_index: " << LCA_new_index << endl; 76 | cout << "LCA_old_index: " << LCA_old_index << endl; 77 | } 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2017 Jakob Kogler 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /Math/ArithmeticSeries.h: -------------------------------------------------------------------------------- 1 | template 2 | T arithmetic_series(T a, T d, int n) { 3 | return (a*2 + d * (n-1)) * n / 2; 4 | } 5 | -------------------------------------------------------------------------------- /Math/BinomialCoefficient.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int MOD = 1'000'000'009; 4 | std::vector> binomial; 5 | 6 | void precompute_binomial_coefficients(int ma) 7 | { 8 | binomial.assign(ma + 1, std::vector(ma + 1)); 9 | for (int n = 0; n <= ma; n++) { 10 | binomial[n][0] = 1; 11 | binomial[n][n] = 1; 12 | for (int k = 1; k < n; k++) { 13 | binomial[n][k] = 14 | (binomial[n - 1][k - 1] + binomial[n - 1][k]) % MOD; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Math/CRT.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Exponentiation.h" 3 | 4 | struct Congruence 5 | { 6 | long long a, m, totient_m; 7 | }; 8 | 9 | class CRT 10 | { 11 | public: 12 | void add_congruence(long long a, long long m, long long totient_m) { 13 | congruences.push_back({a, m, totient_m}); 14 | } 15 | 16 | long long get_unique_solution() { 17 | long long M = 1; 18 | for (const auto& c : congruences) { 19 | M *= c.m; 20 | } 21 | 22 | long long solution = 0; 23 | for (const auto& c : congruences) { 24 | auto b = M / c.m; 25 | solution = (solution + c.a * b % M * power(b, c.totient_m - 1, c.m)) % M; 26 | } 27 | return solution; 28 | } 29 | 30 | std::vector congruences; 31 | }; 32 | -------------------------------------------------------------------------------- /Math/DiscreteLog.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Exponentiation.h" 5 | 6 | /** 7 | * minual x for a^x equiv b mod m 8 | */ 9 | int discrete_log(int a, int b, int m) { 10 | a %= m; 11 | b %= m; 12 | if (a == 0) // assuming that 0^0 is undefined 13 | return b == 0 ? 1 : -1; 14 | 15 | long long k = 1; 16 | int offset = 0, g; 17 | while ((g = std::gcd(a, m)) > 1) { 18 | if (b == k) 19 | return offset; 20 | if (b % g) 21 | return -1; 22 | b /= g; 23 | m /= g; 24 | offset++; 25 | k = (k * a / g) % m; 26 | } 27 | 28 | std::unordered_map baby; 29 | int n = std::sqrt(m) + 1; 30 | 31 | // baby steps 32 | long long cur = b; 33 | for (int q = 0; q <= n; q++) { 34 | baby[cur] = q; 35 | cur = (cur * a) % m; 36 | } 37 | 38 | // giant steps 39 | int an = power(a, n, m); 40 | cur = k; 41 | for (int p = 1; p <= n; p++) { 42 | cur = (cur * an) % m; 43 | if (baby.count(cur)) 44 | return n * p - baby[cur] + offset; 45 | } 46 | return -1; 47 | } 48 | -------------------------------------------------------------------------------- /Math/DiscreteLogs.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "Exponentiation.h" 6 | 7 | /** 8 | * minual x for a^x equiv b mod m for every b in [0, bound) 9 | * assumes m is prime 10 | */ 11 | std::vector discrete_logs(int a, int m, int bound) { 12 | std::vector logs(bound); 13 | a %= m; 14 | logs[0] = a == 0 ? 1 : -1; 15 | logs[1] = a == 0 ? -1 : 0; 16 | 17 | int n = std::sqrt(m / bound) + 1; 18 | int m_n = m / n + 1; 19 | 20 | // giant steps 21 | int an = power(a, n, m); 22 | long long cur = 1; 23 | std::unordered_map giant; 24 | for (int p = 1; p <= m_n; p++) { 25 | cur = (cur * an) % m; 26 | if (giant.count(cur) == 0) 27 | giant[cur] = p; 28 | } 29 | 30 | for (int b = 2; b < bound; b++) { 31 | // baby steps 32 | int best = m; 33 | cur = b; 34 | for (int q = 0; q <= n; q++) { 35 | if (giant.count(cur)) { 36 | int p = giant[cur]; 37 | best = std::min(best, n * p - q); 38 | } 39 | cur = (cur * a) % m; 40 | } 41 | logs[b] = best == m ? -1 : best; 42 | } 43 | return logs; 44 | } 45 | -------------------------------------------------------------------------------- /Math/Divisors.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::vector largest; 5 | 6 | void computePrimesLargest(int n) { 7 | largest.resize(n + 1); 8 | std::iota(largest.begin(), largest.end(), 0); 9 | 10 | for (int i = 2; i <= n; i++) { 11 | if (i == largest[i]) { 12 | for (int j = 2 * i; j <= n; j += i) { 13 | largest[j] = i; 14 | } 15 | } 16 | } 17 | } 18 | 19 | std::vector divisors(int x) { 20 | std::vector d; 21 | d.push_back(1); 22 | 23 | while (x > 1) { 24 | int p = largest[x]; 25 | int c = 0; 26 | while (largest[x] == p) { 27 | c++; 28 | x /= p; 29 | } 30 | std::vector d2; 31 | int b = 1; 32 | for (int j = 0; j <= c; j++) { 33 | for (int x : d) { 34 | d2.push_back(x * b); 35 | } 36 | b *= p; 37 | } 38 | d.swap(d2); 39 | } 40 | return d; 41 | } 42 | -------------------------------------------------------------------------------- /Math/Exponentiation.h: -------------------------------------------------------------------------------- 1 | int MOD = 1e9 + 7; 2 | 3 | int power(long long base, int e, int M=MOD) 4 | { 5 | long long result = 1; 6 | base %= M; 7 | while (e) { 8 | if (e & 1) 9 | result = (result * base) % M; 10 | base = (base * base) % M; 11 | e >>= 1; 12 | } 13 | return result; 14 | } 15 | -------------------------------------------------------------------------------- /Math/ExtendedEuclid.h: -------------------------------------------------------------------------------- 1 | long long extended_gcd(long long a, long long b, long long & x, long long & y) { 2 | if (a == 0) { 3 | x = 0; 4 | y = 1; 5 | return b; 6 | } 7 | long long x1, y1; 8 | long long d = extended_gcd(b%a, a, x1, y1); 9 | x = y1 - (b / a) * x1; 10 | y = x1; 11 | return d; 12 | } 13 | -------------------------------------------------------------------------------- /Math/FFT.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "Modular.h" 6 | #include "MontgomeryModular.h" 7 | 8 | template 9 | void transpose(std::vector> & M) { 10 | auto tmp = M; 11 | M.resize(tmp[0].size()); 12 | for (auto& row : M) 13 | row.resize(tmp.size()); 14 | 15 | for (int i = 0; i < (int)M.size(); i++) { 16 | for (int j = 0; j < (int)M[0].size(); j++) { 17 | M[i][j] = tmp[j][i]; 18 | } 19 | } 20 | } 21 | 22 | class FFT { 23 | public: 24 | FFT(int max_degree=1) { 25 | init(max_degree); 26 | } 27 | 28 | void init(int max_degree) { 29 | int lg = get_lg(max_degree + 1); 30 | reverse.resize(lg + 1); 31 | 32 | ws.resize(lg); 33 | ws[0] = {{1, 0}}; 34 | for (int j = 1; j < lg; j++) { 35 | int sz_level = 1 << j; 36 | ws[j].reserve(sz_level); 37 | double angle = PI / sz_level; 38 | cd z(cos(angle), sin(angle)); 39 | for (const auto x : ws[j-1]) { 40 | ws[j].push_back(x); 41 | ws[j].push_back(x * z); 42 | } 43 | } 44 | } 45 | 46 | int get_lg(int x) { 47 | if (x < 2) 48 | return 2; 49 | // assert(x > 1); 50 | return x ? 32 - __builtin_clz(x - 1) : 0; 51 | } 52 | 53 | void precompute_reverse(int lg) { 54 | int size = 1 << lg; 55 | auto& rev = reverse[lg]; 56 | rev.assign(size, 0); 57 | for (int i = 1; i < size; i++) 58 | rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (lg - 1)); 59 | } 60 | 61 | using cd = std::complex; 62 | using vcd = std::vector; 63 | using vvcd = std::vector; 64 | 65 | void fft(vcd & a, bool inv) { 66 | int lg = get_lg(a.size()); 67 | if (reverse[lg].empty()) 68 | precompute_reverse(lg); 69 | int size = 1 << lg; 70 | 71 | auto& rev = reverse[lg]; 72 | for (int i = 0; i < size; i++) { 73 | if (i < rev[i]) 74 | swap(a[i], a[rev[i]]); 75 | } 76 | 77 | for (int k = 0; k < lg; k++) { 78 | int len = 1 << k; 79 | auto& w = ws[k]; 80 | for (int i = 0; i < size; i += 2*len) { 81 | for (int j = 0; j < len; j++) { 82 | cd u = a[i+j], v = a[i+j+len] * w[j]; 83 | a[i+j] = u + v; 84 | a[i+j+len] = u - v; 85 | } 86 | } 87 | } 88 | 89 | if (inv) { 90 | for (cd & x : a) 91 | x /= size; 92 | std::reverse(a.begin() + 1, a.end()); 93 | } 94 | } 95 | 96 | template 97 | std::vector multiply(std::vector const& a, std::vector const& b) { 98 | int result_size = a.size() + b.size() - 1; 99 | int size = 1 << get_lg(result_size); 100 | vcd f(size, {0, 0}); 101 | int sz = std::max(a.size(), b.size()); 102 | for (int i = 0; i < sz; i++) { 103 | const T& A = i < a.size() ? a[i] : 0; 104 | const T& B = i < b.size() ? b[i] : 0; 105 | f[i] = {(double)A, (double)B}; 106 | } 107 | 108 | fft(f, false); 109 | vcd h(size); 110 | cd factor(0, -0.25); 111 | for (int i = 0; i < size; i++) { 112 | int j = (size - i) & (size - 1); 113 | h[i] = (f[i]*f[i] - std::conj(f[j]*f[j])) * factor; 114 | } 115 | fft(h, true); 116 | h.resize(result_size); 117 | return convert_back(h); 118 | } 119 | 120 | template 121 | std::vector convert_back(vcd const& v) { 122 | std::vector result(v.size()); 123 | for (int i = 0; i < v.size(); i++) 124 | result[i] = v[i].real(); 125 | return result; 126 | } 127 | 128 | void fft2D(vvcd & a, bool inv) { 129 | for (auto& row : a) 130 | fft(row, inv); 131 | transpose(a); 132 | for (auto& row : a) 133 | fft(row, inv); 134 | transpose(a); 135 | } 136 | 137 | void multiply2D(vvcd & a, vvcd & b) { 138 | int result_r = a.size() + b.size() - 1; 139 | int result_c = a[0].size() + b[0].size() - 1; 140 | int size_r = 1 << get_lg(result_r); 141 | int size_c = 1 << get_lg(result_c); 142 | a.resize(size_r); 143 | b.resize(size_r); 144 | for (auto& row : a) 145 | row.resize(size_c); 146 | for (auto& row : b) 147 | row.resize(size_c); 148 | 149 | fft2D(a, false); 150 | fft2D(b, false); 151 | for (int i = 0; i < size_r; i++) { 152 | for (int j = 0; j < size_c; j++) { 153 | a[i][j] *= b[i][j]; 154 | } 155 | } 156 | fft2D(a, true); 157 | 158 | a.resize(result_r); 159 | for (auto& row : a) 160 | row.resize(result_c); 161 | } 162 | 163 | template 164 | std::vector multiply_mod(std::vector const& a, std::vector const& b, int const mod) { 165 | int result_size = a.size() + b.size() - 1; 166 | int size = 1 << get_lg(result_size); 167 | 168 | vcd v1(size), v2(size); 169 | for (int i = 0; i < (int)a.size(); i++) 170 | v1[i] = cd(a[i] >> 15, a[i] & 32767); 171 | for (int i = 0; i < (int)b.size(); i++) 172 | v2[i] = cd(b[i] >> 15, b[i] & 32767); 173 | fft(v1, false); 174 | fft(v2, false); 175 | 176 | vcd r1(size), r2(size); 177 | for (int i = 0; i < size; i++) { 178 | int j = i ? size - i : i; 179 | cd ans1 = (v1[i] + conj(v1[j])) * cd(0.5, 0); 180 | cd ans2 = (v1[i] - conj(v1[j])) * cd(0, -0.5); 181 | cd ans3 = (v2[i] + conj(v2[j])) * cd(0.5, 0); 182 | cd ans4 = (v2[i] - conj(v2[j])) * cd(0, -0.5); 183 | r1[i] = ans1*ans3 + ans1*ans4*cd(0,1); 184 | r2[i] = ans2*ans3 + ans2*ans4*cd(0,1); 185 | } 186 | fft(r1, true); 187 | fft(r2, true); 188 | 189 | std::vector result(result_size); 190 | for (int i = 0; i < result_size; i++) { 191 | long long ans1 = std::llround(r1[i].real()) % mod; 192 | long long ans2 = std::llround(r1[i].imag() + r2[i].real()) % mod; 193 | long long ans3 = std::llround(r2[i].imag()) % mod; 194 | result[i] = ((ans1 << 30) + (ans2 << 15) + ans3) % mod; 195 | } 196 | return result; 197 | } 198 | 199 | private: 200 | std::vector> reverse; 201 | std::vector ws; 202 | const double PI = std::acos(-1); 203 | }; 204 | 205 | template <> 206 | std::vector FFT::convert_back(vcd const& v) { 207 | std::vector result(v.size()); 208 | for (int i = 0; i < (int)v.size(); i++) 209 | result[i] = std::llround(v[i].real()); 210 | return result; 211 | } 212 | 213 | template <> 214 | std::vector FFT::convert_back(vcd const& v) { 215 | std::vector result(v.size()); 216 | for (int i = 0; i < (int)v.size(); i++) 217 | result[i] = std::round(v[i].real()); 218 | return result; 219 | } 220 | 221 | FFT fft; 222 | 223 | template 224 | std::vector from_int_vector(std::vector const& v) { 225 | return std::vector(v.begin(), v.end()); 226 | } 227 | 228 | template 229 | std::vector to_int_vector(std::vector const& v) { 230 | std::vector w; 231 | w.reserve(v.size()); 232 | for (int i = 0; i < (int)v.size(); i++) 233 | w.push_back(v[i].value); 234 | return w; 235 | } 236 | 237 | template 238 | std::vector fft_multiply(std::vector const& a, std::vector const& b) { 239 | return fft.multiply(a, b); 240 | } 241 | 242 | template 243 | std::vector> fft_multiply(std::vector> const& a, std::vector> const& b) { 244 | return from_int_vector>(fft.multiply_mod(to_int_vector(a), to_int_vector(b), MOD)); 245 | } 246 | 247 | template 248 | std::vector> fft_multiply(std::vector> const& a, std::vector> const& b) { 249 | return from_int_vector>(fft.multiply_mod(to_int_vector(a), to_int_vector(b), MOD)); 250 | } 251 | -------------------------------------------------------------------------------- /Math/Factorial.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int MOD = 1'000'000'009; 4 | std::vector factorial; 5 | 6 | void precompute_factorial(int ma) 7 | { 8 | factorial.push_back(1); 9 | for (int i = 1; i <= ma; i++) 10 | factorial.push_back((factorial.back() * i) % MOD); 11 | } 12 | -------------------------------------------------------------------------------- /Math/FastBinomialCoefficient.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Modular.h" 3 | 4 | std::vector f; 5 | std::vector f_inv; 6 | std::vector inv; 7 | 8 | void precompute_factorial(int n) { 9 | int m = ModInt::MOD_value; 10 | f.resize(n + 1, 1); 11 | inv.resize(n+1, 1); 12 | f_inv.resize(n + 1, 1); 13 | for (int i = 2; i <= n; i++) { 14 | f[i] = f[i-1] * i; 15 | inv[i] = -(m / i) * inv[m % i]; 16 | f_inv[i] = f_inv[i-1] * inv[i]; 17 | } 18 | } 19 | 20 | ModInt Binomial(int n, int k) { 21 | return f[n] * f_inv[k] * f_inv[n-k]; 22 | } 23 | -------------------------------------------------------------------------------- /Math/FloorCeilDivision.h: -------------------------------------------------------------------------------- 1 | template 2 | T floor_div(T a, long long b) { 3 | if (b < 0) { 4 | a = -a; 5 | b = -b; 6 | } 7 | return (a < 0 ? a - (b - 1) : a) / b; 8 | } 9 | 10 | template 11 | T ceil_div(T a, long long b) { 12 | if (b < 0) { 13 | a = -a; 14 | b = -b; 15 | } 16 | return (a >= 0 ? a + (b - 1) : a) / b; 17 | } 18 | -------------------------------------------------------------------------------- /Math/Fraction.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Fraction 4 | { 5 | public: 6 | Fraction() : a(0), b(1) {} 7 | Fraction(long long a) : a(a), b(1) {} 8 | Fraction(long long num, long long den) : a(num), b(den) { 9 | long long g = gcd(a, b); 10 | if (b < 0) 11 | g = -g; 12 | a /= g; 13 | b /= g; 14 | } 15 | 16 | Fraction& operator+=(Fraction const& other) { 17 | long long g = gcd(b, other.b); 18 | a = a * (other.b / g) + (b / g) * other.a; 19 | b = b / g * other.b; 20 | return *this; 21 | } 22 | 23 | Fraction operator+(Fraction const& other) const { 24 | Fraction t = *this; t += other; return t; 25 | } 26 | 27 | Fraction& operator-=(Fraction const& other) { 28 | long long g = gcd(b, other.b); 29 | a = a * (other.b / g) - (b / g) * other.a; 30 | b = b / g * other.b; 31 | return *this; 32 | } 33 | 34 | Fraction operator-(Fraction const& other) const { 35 | Fraction t = *this; t -= other; return t; 36 | } 37 | 38 | Fraction& operator*=(Fraction const& other) { 39 | long long g1 = gcd(a, other.b); 40 | long long g2 = gcd(b, other.a); 41 | a = (a / g1) * (other.a / g2); 42 | b = (b / g2) * (other.b / g1); 43 | return *this; 44 | } 45 | 46 | Fraction operator*(Fraction const& other) const { 47 | Fraction t = *this; t *= other; return t; 48 | } 49 | 50 | Fraction& operator/=(Fraction const& other) { 51 | *this *= Fraction(copy_sign(other.b, other.a), std::abs(other.a)); 52 | return *this; 53 | } 54 | 55 | Fraction operator/(Fraction const& other) const { 56 | Fraction t = *this; t /= other; return t; 57 | } 58 | 59 | bool operator<(Fraction const& other) const { 60 | return a * other.b < other.a * b; 61 | } 62 | 63 | bool operator<=(Fraction const& other) const { 64 | return a * other.b <= other.a * b; 65 | } 66 | 67 | bool operator>(Fraction const& other) const { 68 | return a * other.b > other.a * b; 69 | } 70 | 71 | bool operator>=(Fraction const& other) const { 72 | return a * other.b >= other.a * b; 73 | } 74 | 75 | bool operator==(Fraction const& other) const { 76 | return a * other.b == other.a * b; 77 | } 78 | 79 | bool operator!=(Fraction const& other) const { 80 | return a * other.b != other.a * b; 81 | } 82 | 83 | long long floor() const { 84 | return a / b; 85 | } 86 | 87 | operator double() const { 88 | return (double)a / b; 89 | } 90 | 91 | static long long gcd(long long a, long long b) { 92 | a = std::abs(a); 93 | b = std::abs(b); 94 | while (b) { 95 | a %= b; 96 | std::swap(a, b); 97 | } 98 | return a; 99 | } 100 | 101 | static long long copy_sign(long long a, long long b) { 102 | return b >= 0 ? a : -a; 103 | } 104 | 105 | long long a, b; 106 | }; 107 | -------------------------------------------------------------------------------- /Math/GeometricSeries.h: -------------------------------------------------------------------------------- 1 | template 2 | T geometric_series(T a, T r, int n) { 3 | if (r != 1) 4 | return a * (1 - power(r, n)) / (1 - r); 5 | else 6 | return a * n; 7 | } 8 | -------------------------------------------------------------------------------- /Math/InverseModPrime.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int MOD = 1'000'000'007; 4 | 5 | long long power(long long base, int e, int M=MOD) 6 | { 7 | long long result = 1; 8 | base %= M; 9 | while (e) { 10 | if (e & 1) 11 | result = (result * base) % M; 12 | base = (base * base) % M; 13 | e >>= 1; 14 | } 15 | return result; 16 | } 17 | 18 | auto inverse(long long x) { 19 | return power(x, MOD - 2); 20 | } 21 | 22 | auto inverse(std::vector v) { 23 | for (auto& x : v) 24 | x = inverse(x); 25 | return v; 26 | } 27 | -------------------------------------------------------------------------------- /Math/IsPrime.h: -------------------------------------------------------------------------------- 1 | bool isPrime(int x) { 2 | if (x == 1) return false; 3 | if (x == 2) 4 | return true; 5 | if (x % 2 == 0) 6 | return false; 7 | for (int div = 3; div * div <= x; div+=2) { 8 | if (x % div == 0) return false; 9 | } 10 | return true; 11 | } 12 | -------------------------------------------------------------------------------- /Math/LinearDiophantine.h: -------------------------------------------------------------------------------- 1 | template 2 | T floor_div(T a, long long b) { 3 | return (a < 0 ? a - (b - 1) : a) / b; 4 | } 5 | 6 | template 7 | T ceil_div(T a, long long b) { 8 | return (a >= 0 ? a + (b - 1) : a) / b; 9 | } 10 | 11 | template 12 | class LinearDiophantine { 13 | public: 14 | static T extended_gcd(T a, T b, T& x, T& y) { 15 | if (a == 0) { 16 | x = 0; 17 | y = 1; 18 | return b; 19 | } 20 | long long d = extended_gcd(b % a, a, y, x); 21 | x -= b / a * y; 22 | return d; 23 | } 24 | 25 | static bool solve(T a, T b, T c, T& x, T& y, T& g) { 26 | if (a == 0) { 27 | if (b == 0) { 28 | x = y = 0; 29 | g = 1; 30 | return c == 0; 31 | } else { 32 | x = 0; 33 | y = c / b; 34 | g = abs(b); 35 | return c % b == 0; 36 | } 37 | } else { 38 | if (b == 0) { 39 | x = c / a; 40 | y = 0; 41 | g = abs(b); 42 | return c % a == 0; 43 | } else { 44 | g = extended_gcd(a, b, x, y); 45 | T dx = c / a; 46 | c %= a; 47 | T dy = c / b; 48 | c %= b; 49 | x = dx + multiply_mod(x, c / g, b); 50 | y = dy + multiply_mod(y, c / g, a); 51 | g = abs(g); 52 | return c % g == 0; 53 | } 54 | } 55 | } 56 | 57 | static void smallest_non_negative_x(T a, T b, T& x, T& y, T g) { 58 | long long k; 59 | if (b >= 0) 60 | k = ceil_div(-x, b / g); 61 | else 62 | k = floor_div(x, -b / g); 63 | x += k * (b / g); 64 | y -= k * (a / g); 65 | } 66 | 67 | static void smallest_non_negative_y(T a, T b, T& x, T& y, T g) { 68 | long long k; 69 | if (a >= 0) 70 | k = ceil_div(-y, a / g); 71 | else 72 | k = floor_div(y, -a / g); 73 | x += k * (b / g); 74 | y -= k * (a / g); 75 | } 76 | 77 | static T multiply_mod(T x, T y, T m) { 78 | int sign = (x < 0 ? -1 : 1) * (y < 0 ? -1 : 1); 79 | x = abs(x) % m; 80 | y = abs(y) % m; 81 | T res = 0; 82 | while (y) { 83 | if (y & 1) 84 | res = (res + x) % m; 85 | x = (x << 1) % m; 86 | y >>= 1; 87 | } 88 | return sign * res; 89 | } 90 | }; 91 | -------------------------------------------------------------------------------- /Math/Matrix.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | template 8 | class Vector; 9 | 10 | template 11 | class StrideIter 12 | { 13 | public: 14 | using value_type = typename std::iterator_traits::value_type; 15 | using reference = typename std::iterator_traits::reference; 16 | using difference_type = typename std::iterator_traits::difference_type; 17 | StrideIter(IterT x, int step) : m(x), step(step) { } 18 | 19 | StrideIter& operator++( ) { m += step; return *this; } 20 | StrideIter operator++(int) { auto tmp = *this; m += step; return tmp; } 21 | reference operator[](const difference_type n) { return m[n * step]; } 22 | value_type operator[](const difference_type n) const { return m[n * step]; } 23 | reference operator*( ) { return *m; } 24 | 25 | friend bool operator==(const StrideIter& x, const StrideIter& y) { return x.m == y.m; } 26 | friend bool operator!=(const StrideIter& x, const StrideIter& y) { return x.m != y.m; } 27 | private: 28 | IterT m; 29 | difference_type step; 30 | }; 31 | 32 | template 33 | class Vector; 34 | 35 | template 36 | class VecView { 37 | public: 38 | using T = typename IterT::value_type; 39 | VecView(IterT begin_, IterT end_) : begin_(begin_), end_(end_) {} 40 | T& operator[](int idx) { return begin_[idx]; } 41 | T operator[](int idx) const { return begin_[idx]; } 42 | T sum() const { return std::accumulate(begin(), end(), T(0)); } 43 | T min() const { return *std::min_element(begin(), end()); } 44 | T max() const { return *std::max_element(begin(), end()); } 45 | IterT begin() const { return begin_; } 46 | IterT end() const { return end_; } 47 | friend std::ostream& operator<<(std::ostream& os, VecView const& vv) { 48 | os << "["; 49 | for (auto it = vv.begin(); it != vv.end(); ++it) { 50 | if (it != vv.begin()) 51 | os << ", "; 52 | os << *it; 53 | } 54 | return os << "]"; 55 | } 56 | Vector copy() const { 57 | Vector res; 58 | for (const auto& x : *this) 59 | res.push_back(x); 60 | return res; 61 | } 62 | private: 63 | IterT begin_, end_; 64 | int step; 65 | }; 66 | 67 | template 68 | class Vector : public std::vector { 69 | public: 70 | Vector(int n = 0, T init = 0) : std::vector(n, init) {} 71 | Vector(std::initializer_list const& data) : std::vector(data) {} 72 | using Vec = Vector; 73 | 74 | T sum() const { 75 | return std::accumulate(this->begin(), this->end(), T(0)); 76 | } 77 | T min() const { 78 | return *std::min_element(this->begin(), this->end()); 79 | } 80 | T max() const { 81 | return *std::max_element(this->begin(), this->end()); 82 | } 83 | 84 | friend Vec& operator+=(Vec& v, Vec const& w) { 85 | int n = v.size(); 86 | for (int i = 0; i < n; i++) 87 | v[i] += w[i]; 88 | return v; 89 | } 90 | friend Vec operator+(Vec const& v, Vec const& w) { 91 | Vec r = v; 92 | return r += w; 93 | } 94 | friend Vec& operator-=(Vec& v, Vec const& w) { 95 | int n = v.size(); 96 | for (int i = 0; i < n; i++) 97 | v[i] -= w[i]; 98 | return v; 99 | } 100 | friend Vec operator-(Vec const& v, Vec const& w) { 101 | Vec r = v; 102 | return r -= w; 103 | } 104 | }; 105 | 106 | template 107 | class Matrix { 108 | public: 109 | Matrix(int rows, int columns, T init = 0) 110 | : rows(rows), columns(columns), data(rows * columns, init) { } 111 | using Mat = Matrix; 112 | using Vec = Vector; 113 | 114 | Matrix(std::initializer_list> const& ilist) 115 | : rows(ilist.size()), columns(ilist.begin()->size()), data(0) { 116 | data.reserve(rows * columns); 117 | for (auto& row : ilist) { 118 | for (auto& elem : row) { 119 | data.push_back(elem); 120 | } 121 | } 122 | } 123 | 124 | friend Mat& operator+=(Mat& A, Mat const& B) { 125 | A.data += B.data; 126 | return A; 127 | } 128 | friend Mat operator+(Mat const& A, Mat const& B) { 129 | Mat C = A; 130 | return C += B; 131 | } 132 | friend Mat& operator-=(Mat& A, Mat const& B) { 133 | A.data -= B.data; 134 | return A; 135 | } 136 | friend Mat operator-(Mat const& A, Mat const& B) { 137 | Mat C = A; 138 | return C -= B; 139 | } 140 | friend Vec operator*(Mat const& M, Vec const& v) { 141 | Vec res(v.size(), 0); 142 | for (int i = 0; i < (int)res.size(); i++) { 143 | for (int j = 0; j < (int)res.size(); j++) 144 | res[i] += M.get(i, j) * v[j]; 145 | } 146 | return res; 147 | } 148 | friend Vec operator*(Vec const& v, Mat const& M) { 149 | return M.transpose() * v; 150 | } 151 | Mat transpose() const { 152 | const int blocksize = 32; 153 | Mat dst(columns, rows); 154 | for (int i = 0; i < rows; i += blocksize) { 155 | for (int j = 0; j < columns; j += blocksize) { 156 | int iend = std::min(rows, i + blocksize); 157 | int jend = std::min(columns, j + blocksize); 158 | for (int k = i; k < iend; ++k) { 159 | for (int l = j; l < jend; ++l) 160 | dst.get(l, k) = get(k, l); 161 | } 162 | } 163 | } 164 | return dst; 165 | } 166 | friend Mat operator*(Mat const& A, Mat const& B) { 167 | assert(A.columns == B.rows); 168 | 169 | Matrix C(A.rows, B.columns); 170 | 171 | std::vector Bcolj(B.rows); 172 | for (int j = 0; j < B.columns; j++) { 173 | for (int k = 0; k < B.rows; k++) 174 | Bcolj[k] = B.get(k, j); 175 | 176 | for (int i = 0; i < A.rows; i++) { 177 | T s = 0; 178 | for (int k = 0; k < B.rows; k++) 179 | s += A.get(i, k) * Bcolj[k]; 180 | C.get(i, j) = s; 181 | } 182 | } 183 | return C; 184 | } 185 | Mat get_quarter(int i, int j) const { 186 | int offset_x = i == 2 ? rows / 2 : 0; 187 | int offset_y = j == 2 ? columns / 2 : 0; 188 | Mat res(rows / 2, columns / 2); 189 | for (int x = 0; x < res.rows; x++) 190 | for (int y = 0; y < res.columns; y++) 191 | res.get(x, y) = get(x + offset_x, y + offset_y); 192 | return res; 193 | } 194 | void set_quarter(Mat const& A, int i, int j) { 195 | int offset_x = i == 2 ? rows / 2 : 0; 196 | int offset_y = j == 2 ? columns / 2 : 0; 197 | for (int x = 0; x < A.rows; x++) 198 | for (int y = 0; y < A.columns; y++) 199 | get(x + offset_x, y + offset_y) = A.get(x, y); 200 | } 201 | friend Mat strassen(Mat const& A, Mat const& B) { 202 | assert(A.rows == A.columns && A.columns == B.rows && B.rows == B.columns && (A.rows & (A.rows-1)) == 0); 203 | 204 | if (A.rows <= 64) 205 | return A * B; 206 | 207 | Mat C(A.rows, B.columns); 208 | auto A11 = A.get_quarter(1, 1); 209 | auto A12 = A.get_quarter(1, 2); 210 | auto A21 = A.get_quarter(2, 1); 211 | auto A22 = A.get_quarter(2, 2); 212 | auto B11 = B.get_quarter(1, 1); 213 | auto B12 = B.get_quarter(1, 2); 214 | auto B21 = B.get_quarter(2, 1); 215 | auto B22 = B.get_quarter(2, 2); 216 | auto M1 = strassen(A11 + A22, B11 + B22); 217 | auto M2 = strassen(A21 + A22, B11); 218 | auto M3 = strassen(A11, B12 - B22); 219 | auto M4 = strassen(A22, B21 - B11); 220 | auto M5 = strassen(A11 + A12, B22); 221 | auto M6 = strassen(A21 - A11, B11 + B12); 222 | auto M7 = strassen(A12 - A22, B21 + B22); 223 | auto C11 = M1 + M4 - M5 + M7; 224 | auto C12 = M3 + M5; 225 | auto C21 = M2 + M4; 226 | auto C22 = M1 - M2 + M3 + M6; 227 | C.set_quarter(C11, 1, 1); 228 | C.set_quarter(C12, 1, 2); 229 | C.set_quarter(C21, 2, 1); 230 | C.set_quarter(C22, 2, 2); 231 | return C; 232 | } 233 | 234 | static Mat identity(int n) { 235 | Mat identity(n, n); 236 | for (int i = 0; i < n; i++) { 237 | identity.get(i, i) = 1; 238 | } 239 | return identity; 240 | } 241 | 242 | int get_idx(int row, int column) const { 243 | return row * columns + column; 244 | } 245 | T& get(int row, int column) { 246 | return data[get_idx(row, column)]; 247 | } 248 | T get(int row, int column) const { 249 | return data[get_idx(row, column)]; 250 | } 251 | 252 | using IterForView = StrideIter::iterator>; 253 | using IterForViewConst = StrideIter::const_iterator>; 254 | VecView row(int row_idx) { 255 | auto beg = IterForView(data.begin() + row_idx * columns, 1); 256 | auto end = IterForView(data.begin() + (row_idx + 1) * columns, 1); 257 | return {beg, end}; 258 | } 259 | VecView const row(int row_idx) const { 260 | auto beg = IterForViewConst(data.cbegin() + row_idx * columns, 1); 261 | auto end = IterForViewConst(data.cbegin() + (row_idx + 1) * columns, 1); 262 | return {beg, end}; 263 | } 264 | VecView column(int col_idx) { 265 | auto beg = IterForView(data.begin() + col_idx, columns); 266 | auto end = IterForView(data.begin() + col_idx + rows * columns, columns); 267 | return {beg, end}; 268 | } 269 | VecView const column(int col_idx) const { 270 | auto beg = IterForViewConst(data.cbegin() + col_idx, columns); 271 | auto end = IterForViewConst(data.cbegin() + col_idx + rows * columns, columns); 272 | return {beg, end}; 273 | } 274 | VecView operator[](int row_idx) { 275 | return row(row_idx); 276 | } 277 | VecView const operator[](int row_idx) const { 278 | return row(row_idx); 279 | } 280 | T trace() const { 281 | assert(rows == columns); 282 | T sum = 0; 283 | for (int i = 0; i < rows; i++) { 284 | sum += get(i, i); 285 | } 286 | return sum; 287 | } 288 | T sum() const { 289 | return data.sum(); 290 | } 291 | T min() const { 292 | return data.min(); 293 | } 294 | T max() const { 295 | return data.max(); 296 | } 297 | 298 | /** 299 | * Finds the shortest path between two adj matrices with weight infos 300 | */ 301 | Mat min_weight_paths(Mat const& other, T const INF) { 302 | assert(columns == other.rows); 303 | 304 | Mat result(rows, other.columns); 305 | Vector other_colj(other.rows); 306 | for (int column = 0; column < other.columns; column++) { 307 | for (int k = 0; k < other.rows; k++) 308 | other_colj[k] = other.get(k, column); 309 | 310 | for (int row = 0; row < rows; row++) { 311 | T best = INF; 312 | for (int k = 0; k < other.rows; k++) { 313 | T left = get(row, k); 314 | T right = other_colj[k]; 315 | if (left != INF && right != INF) 316 | best = std::min(best, left + right); 317 | } 318 | result.get(row, column) = best; 319 | } 320 | } 321 | return result; 322 | } 323 | 324 | friend std::ostream& operator<<(std::ostream& os, Mat const& A) { 325 | os << "[\n"; 326 | for (int row = 0; row < A.rows; row++) { 327 | os << " ["; 328 | for (int col = 0; col < A.columns; col++) { 329 | os << '\t' << A[row][col]; 330 | } 331 | os << " ]"; 332 | if (row + 1 < A.rows) 333 | os << ","; 334 | os << '\n'; 335 | } 336 | os << "]"; 337 | return os; 338 | } 339 | 340 | int rows, columns; 341 | Vector data; 342 | }; 343 | 344 | template 345 | Matrix power(Matrix base, long long e) { 346 | auto result = Matrix::identity(base.rows); 347 | while (e) { 348 | if (e & 1) 349 | result = result * base; 350 | base = base * base; 351 | e >>= 1; 352 | } 353 | return result; 354 | } 355 | 356 | /** 357 | * Finds the shortest paths of length k given an adjacency matrix with weight infos 358 | */ 359 | template 360 | Matrix min_weight_paths(Matrix base, long long k, T const INF) { 361 | Matrix result(base.rows, base.rows); 362 | while (k) { 363 | if (k & 1) 364 | result = result.min_weight_paths(base, INF); 365 | base = base.min_weight_paths(base, INF); 366 | k >>= 1; 367 | } 368 | return result; 369 | } 370 | -------------------------------------------------------------------------------- /Math/Matrix2.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class Matrix2 { 5 | public: 6 | using Arr4 = std::array; 7 | 8 | Matrix2(Arr4 const& data) : data(data) {} 9 | 10 | Matrix2& operator+=(Matrix2 const& other) { 11 | for (int i = 0; i < 4; i++) 12 | data[i] += other.data[i]; 13 | return *this; 14 | } 15 | 16 | Matrix2 operator+(Matrix2 const& other) { 17 | Matrix2 cpy = *this; 18 | return cpy += other; 19 | } 20 | 21 | Matrix2& operator-=(Matrix2 const& other) { 22 | for (int i = 0; i < 4; i++) 23 | data[i] -= other.data[i]; 24 | return *this; 25 | } 26 | 27 | Matrix2 operator-(Matrix2 const& other) { 28 | Matrix2 cpy = *this; 29 | return cpy -= other; 30 | } 31 | 32 | Matrix2 operator*(Matrix2 const& other) { 33 | return Matrix2({data[0]*other.data[0] + data[1]*other.data[2], 34 | data[0]*other.data[1] + data[1]*other.data[3], 35 | data[2]*other.data[0] + data[3]*other.data[2], 36 | data[2]*other.data[1] + data[3]*other.data[3]}); 37 | } 38 | 39 | Arr4 data; 40 | }; 41 | 42 | template 43 | Matrix2 power(Matrix2 base, long long e) { 44 | auto result = Matrix2({1, 0, 0, 1}); 45 | while (e) { 46 | if (e & 1) 47 | result = result * base; 48 | base = base * base; 49 | e >>= 1; 50 | } 51 | return result; 52 | } 53 | -------------------------------------------------------------------------------- /Math/MatrixStrassen.h: -------------------------------------------------------------------------------- 1 | #include "Matrix.h" 2 | 3 | template 4 | Matrix operator-(Matrix const& A, Matrix const& B) { 5 | auto res = A; 6 | for (int i = 0; i < (int)res.size(); i++) { 7 | for (int j = 0; j < (int)res[0].size(); j++) { 8 | res[i][j] -= B[i][j]; 9 | } 10 | } 11 | return res; 12 | } 13 | 14 | template 15 | Matrix get_quarter(Matrix const& M, int quadrant) { 16 | int n = M.size() / 2; 17 | int offset_x = 0; 18 | int offset_y = 0; 19 | if (quadrant > 2) 20 | offset_x = n; 21 | if ((quadrant & 2) == 0) 22 | offset_y = n; 23 | 24 | Matrix res(n, n); 25 | for (int x = 0; x < n; x++) { 26 | for (int y = 0; y < n; y++) { 27 | res[x][y] = M[x + offset_x][y + offset_y]; 28 | } 29 | } 30 | return res; 31 | } 32 | 33 | template 34 | void set_quarter(Matrix & M, Matrix const& A, int quadrant) { 35 | int n = M.size() / 2; 36 | int offset_x = 0; 37 | int offset_y = 0; 38 | if (quadrant > 2) 39 | offset_x = n; 40 | if ((quadrant & 2) == 0) 41 | offset_y = n; 42 | 43 | for (int x = 0; x < n; x++) { 44 | for (int y = 0; y < n; y++) { 45 | M[x + offset_x][y + offset_y] = A[x][y]; 46 | } 47 | } 48 | } 49 | 50 | template 51 | Matrix strassen(Matrix const& A, Matrix const& B, int max_trivial=64) { 52 | int n = A.size(); 53 | if (n <= max_trivial) 54 | return A * B; 55 | 56 | Matrix C(n, n); 57 | auto A11 = get_quarter(A, 2); 58 | auto A12 = get_quarter(A, 1); 59 | auto A21 = get_quarter(A, 3); 60 | auto A22 = get_quarter(A, 4); 61 | auto B11 = get_quarter(B, 2); 62 | auto B12 = get_quarter(B, 1); 63 | auto B21 = get_quarter(B, 3); 64 | auto B22 = get_quarter(B, 4); 65 | auto M1 = strassen(A11 + A22, B11 + B22, max_trivial); 66 | auto M2 = strassen(A21 + A22, B11, max_trivial); 67 | auto M3 = strassen(A11, B12 - B22, max_trivial); 68 | auto M4 = strassen(A22, B21 - B11, max_trivial); 69 | auto M5 = strassen(A11 + A12, B22, max_trivial); 70 | auto M6 = strassen(A21 - A11, B11 + B12, max_trivial); 71 | auto M7 = strassen(A12 - A22, B21 + B22, max_trivial); 72 | auto C11 = M1 + M4 - M5 + M7; 73 | auto C12 = M3 + M5; 74 | auto C21 = M2 + M4; 75 | auto C22 = M1 - M2 + M3 + M6; 76 | set_quarter(C, C11, 2); 77 | set_quarter(C, C12, 1); 78 | set_quarter(C, C21, 3); 79 | set_quarter(C, C22, 4); 80 | return C; 81 | } 82 | -------------------------------------------------------------------------------- /Math/MatrixTransition.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | class Matrix : public std::vector> { 6 | public: 7 | Matrix(int n, int m, T init) 8 | : std::vector>(n, std::vector(m, init)) {} 9 | }; 10 | 11 | constexpr auto INF = std::numeric_limits::max(); 12 | 13 | template 14 | std::vector operator*(std::vector const& v, Matrix const& M) { 15 | auto res = v; 16 | for (int i = 0; i < (int)res.size(); i++) { 17 | T cost = INF; 18 | for (int j = 0; j < (int)res.size(); j++) 19 | cost = min(cost, v[j] + M[j][i]); 20 | res[i] = cost; 21 | } 22 | return res; 23 | } 24 | 25 | template 26 | Matrix operator*(Matrix const& A, Matrix const& B) { 27 | auto res = A; 28 | for (int i = 0; i < (int)res.size(); i++) 29 | res[i] = A[i] * B; 30 | return res; 31 | } 32 | -------------------------------------------------------------------------------- /Math/MillerRabin.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using u64 = uint64_t; 5 | 6 | u64 power(u64 base, u64 e, u64 mod) { 7 | u64 result = 1; 8 | base %= mod; 9 | while (e) { 10 | if (e & 1) 11 | result = result * base % mod; 12 | base = base * base % mod; 13 | e >>= 1; 14 | } 15 | return result; 16 | } 17 | 18 | bool SPRP(u64 n, u64 a, u64 d, int r) { 19 | u64 x = power(a, d, n); 20 | if (x == 1 || x == n - 1) 21 | return true; 22 | for (int s = 1; s < r; s++) { 23 | x = x * x % n; 24 | if (x == n - 1) 25 | return true; 26 | } 27 | return false; 28 | }; 29 | 30 | bool MillerRabin(u64 n) { 31 | if (n < 2) 32 | return false; 33 | 34 | int r = 0; 35 | u64 d = n - 1; 36 | while ((d & 1) == 0) { 37 | d >>= 1; 38 | r++; 39 | } 40 | 41 | for (int a : {2, 3, 5, 7}) { 42 | if (a == n) 43 | return true; 44 | if (!SPRP(n, a, d, r)) 45 | return false; 46 | } 47 | return true; 48 | } 49 | 50 | bool isPrime(u64 n) { 51 | for (int p : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}) { 52 | if (n == p) 53 | return true; 54 | if (n % p == 0) 55 | return false; 56 | } 57 | return MillerRabin(n); 58 | } 59 | -------------------------------------------------------------------------------- /Math/MillerRabin64.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using u64 = uint64_t; 5 | using u128 = __uint128_t; 6 | 7 | u64 power(u64 base, u64 e, u64 mod) { 8 | u64 result = 1; 9 | base %= mod; 10 | while (e) { 11 | if (e & 1) 12 | result = (u128)result * base % mod; 13 | base = (u128)base * base % mod; 14 | e >>= 1; 15 | } 16 | return result; 17 | } 18 | 19 | bool SPRP(u64 n, u64 a, u64 d, int r) { 20 | u64 x = power(a, d, n); 21 | if (x == 1 || x == n - 1) 22 | return true; 23 | for (int s = 1; s < r; s++) { 24 | x = (u128)x * x % n; 25 | if (x == n - 1) 26 | return true; 27 | } 28 | return false; 29 | }; 30 | 31 | bool MillerRabin(u64 n) { 32 | if (n < 2) 33 | return false; 34 | 35 | int r = 0; 36 | u64 d = n - 1; 37 | while ((d & 1) == 0) { 38 | d >>= 1; 39 | r++; 40 | } 41 | 42 | for (int p : {2, 3, 5, 13, 19, 73, 193, 407521, 299210837}) { 43 | if (p == n) 44 | return true; 45 | } 46 | for (int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) { 47 | if (!SPRP(n, a, d, r)) 48 | return false; 49 | } 50 | return true; 51 | } 52 | 53 | bool isPrime(u64 n) { 54 | for (int p : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}) { 55 | if (n == p) 56 | return true; 57 | if (n % p == 0) 58 | return false; 59 | } 60 | return MillerRabin(n); 61 | } 62 | -------------------------------------------------------------------------------- /Math/Modular.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | class Modular { 6 | // using ModInt = Modular<1'000'000'007>; 7 | public: 8 | Modular(long long v=0) { 9 | value = v % MOD; 10 | if (value < 0) 11 | value += MOD; 12 | } 13 | 14 | Modular(long long a, long long b) : value(0) { 15 | *this += a; 16 | *this /= b; 17 | } 18 | 19 | Modular& operator+=(Modular const& b) { 20 | value += b.value; 21 | if (value >= MOD) 22 | value -= MOD; 23 | return *this; 24 | } 25 | 26 | Modular& operator-=(Modular const& b) { 27 | value -= b.value; 28 | if (value < 0) 29 | value += MOD; 30 | return *this; 31 | } 32 | 33 | Modular& operator*=(Modular const& b) { 34 | value = (long long)value * b.value % MOD; 35 | return *this; 36 | } 37 | 38 | friend Modular power(Modular a, long long e) { 39 | Modular res = 1; 40 | while (e) { 41 | if (e & 1) 42 | res *= a; 43 | a *= a; 44 | e >>= 1; 45 | } 46 | return res; 47 | } 48 | 49 | friend Modular inverse(Modular a) { 50 | return power(a, MOD - 2); 51 | } 52 | 53 | Modular& operator/=(Modular const& b) { 54 | return *this *= inverse(b); 55 | } 56 | 57 | friend Modular operator+(Modular a, Modular const b) { 58 | return a += b; 59 | } 60 | 61 | friend Modular operator-(Modular a, Modular const b) { 62 | return a -= b; 63 | } 64 | 65 | friend Modular operator-(Modular const a) { 66 | return 0 - a; 67 | } 68 | 69 | friend Modular operator*(Modular a, Modular const b) { 70 | return a *= b; 71 | } 72 | 73 | friend Modular operator/(Modular a, Modular const b) { 74 | return a /= b; 75 | } 76 | 77 | friend std::ostream& operator<<(std::ostream &os, Modular const& a) { 78 | return os << a.value; 79 | } 80 | 81 | friend std::istream& operator>>(std::istream &is, Modular& a) { 82 | is >> a.value; 83 | a.value %= MOD; 84 | if (a.value < 0) 85 | a.value += MOD; 86 | return is; 87 | } 88 | 89 | friend bool operator==(Modular const& a, Modular const& b) { 90 | return a.value == b.value; 91 | } 92 | 93 | friend bool operator!=(Modular const& a, Modular const& b) { 94 | return a.value != b.value; 95 | } 96 | 97 | friend Modular& operator++(Modular& a, int) { 98 | return a += 1; 99 | } 100 | 101 | friend Modular operator++(Modular const& a, int) { 102 | return Modular(a)++; 103 | } 104 | 105 | friend Modular& operator--(Modular& a, int) { 106 | return a -= 1; 107 | } 108 | 109 | friend Modular operator--(Modular const& a, int) { 110 | return Modular(a)--; 111 | } 112 | 113 | int value; 114 | static const int MOD_value = MOD; 115 | }; 116 | -------------------------------------------------------------------------------- /Math/MontgomeryModular.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | class MontgomeryModular { 8 | public: 9 | using u64 = uint64_t; 10 | using u32 = uint32_t; 11 | using i32 = int32_t; 12 | using MM = MontgomeryModular; 13 | 14 | MontgomeryModular(u32 value=0) : value(mult(value, r2)) {} 15 | 16 | MM& operator+=(MM const& other) { 17 | value += other.value; 18 | value -= (((i32)mod - 1 - (i32)value) >> 31) & (i32)mod; 19 | return *this; 20 | } 21 | 22 | MM operator+(MM const& other) const { 23 | MM cpy = *this; 24 | return cpy += other; 25 | } 26 | 27 | MM& operator-=(MM const& other) { 28 | value += mod - other.value; 29 | value -= (((i32)mod - 1 - (i32)value) >> 31) & (i32)mod; 30 | return *this; 31 | } 32 | 33 | MM operator-(MM const& other) const { 34 | MM cpy = *this; 35 | return cpy -= other; 36 | } 37 | 38 | MM operator-() const { 39 | return MM(0) - *this; 40 | } 41 | 42 | MM& operator*=(MM const& other) { 43 | value = mult(value, other.value); 44 | return *this; 45 | } 46 | 47 | MM operator*(MM const& other) const { 48 | MM cpy = *this; 49 | return cpy *= other; 50 | } 51 | 52 | MM& operator/=(MM const& other) { 53 | return *this *= inverse(other); 54 | } 55 | 56 | MM operator/(MM const& other) { 57 | MM cpy = *this; 58 | return cpy /= other; 59 | } 60 | 61 | friend MM inverse(MM a) { 62 | MM x; 63 | x.value = MM::phase2(MM::reduce(a.value)); 64 | return x; 65 | } 66 | 67 | friend MM power(MM a, long long e) { 68 | MM res(1); 69 | while (e) { 70 | if (e & 1) 71 | res *= a; 72 | a *= a; 73 | e >>= 1; 74 | } 75 | return res; 76 | } 77 | 78 | u32 normal() const { 79 | return reduce(value); 80 | } 81 | 82 | friend std::ostream& operator<<(std::ostream& os, MontgomeryModular const& mm) { 83 | return os << mm.normal(); 84 | } 85 | 86 | bool operator==(MontgomeryModular const& mm) const { 87 | return value == mm.value; 88 | } 89 | 90 | bool operator!=(MontgomeryModular const& mm) const { 91 | return value != mm.value; 92 | } 93 | 94 | static MM init_inverse(u32 a) { 95 | MM x; 96 | x.value = phase2(a); 97 | return x; 98 | } 99 | 100 | u32 value; 101 | static const u32 mod = MOD; 102 | 103 | private: 104 | static u32 reduce(u64 x) { 105 | u32 xlow = x; 106 | u32 xhigh = x >> 32; 107 | u32 q = xlow * inv; 108 | i32 a = xhigh - ((u64(q) * mod) >> 32); 109 | a += mod; 110 | a -= (((i32)mod - 1 - (i32)a) >> 31) & (i32)mod; 111 | return a; 112 | } 113 | 114 | u32 mult(u32 a, u32 b) const { 115 | return reduce(u64(a) * b); 116 | } 117 | 118 | static constexpr u32 compute_inv(u32 mod) { 119 | u32 inv = 1; 120 | for (int i = 0; i < 5; i++) 121 | inv *= 2 - mod * inv; 122 | return inv; 123 | } 124 | 125 | static constexpr u32 compute_r2(u32 mod) { 126 | u32 r2 = 1; 127 | for (int i = 0; i < 64; i++) { 128 | r2 <<= 1; 129 | if (r2 >= mod) 130 | r2 -= mod; 131 | } 132 | return r2; 133 | } 134 | 135 | static const u32 inv = compute_inv(MOD); 136 | static const u32 r2 = compute_r2(MOD); 137 | 138 | // Algorithm A from paper "Improvement to Montgomery Modular Inverse Algorithm" 139 | static std::pair phase1(u32 a) { 140 | auto p = mod; 141 | auto u = p; 142 | auto v = a; 143 | auto r = 0; 144 | auto s = 1; 145 | auto k = 0; 146 | while (v > 0) { 147 | if ((u & 1) == 0) { 148 | u >>= 1; 149 | s <<= 1; 150 | } else if ((v & 1) == 0) { 151 | v >>= 1; 152 | r <<= 1; 153 | } else if (u > v) { 154 | u = (u - v) >> 1; 155 | r += s; 156 | s <<= 1; 157 | } else { 158 | v = (v - u) >> 1; 159 | s += r; 160 | r <<= 1; 161 | } 162 | k++; 163 | if (r >= p) 164 | r -= p; 165 | } 166 | return std::make_pair(p - r, k); 167 | } 168 | 169 | static u32 phase2(u32 a) { 170 | auto [r, k] = phase1(a); 171 | for (int i = 0; i < k - 32; i++) { 172 | if ((r & 1) == 0) 173 | r >>= 1; 174 | else 175 | r = (r + mod) >> 1; 176 | } 177 | for (int i = 0; i < 32 - k; i++) { 178 | r <<= 1; 179 | if (r >= mod) 180 | r -= mod; 181 | } 182 | return r; 183 | } 184 | }; 185 | -------------------------------------------------------------------------------- /Math/NegativeBase.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::vector to_negative_base(int x, int pos_base) { 4 | std::vector coeff; 5 | while (x) { 6 | int rem = x % pos_base; 7 | if (rem < 0) rem += pos_base; 8 | coeff.push_back(rem); 9 | x -= rem; 10 | x /= -pos_base; 11 | } 12 | return coeff; 13 | } 14 | -------------------------------------------------------------------------------- /Math/NevilleInterpolation.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct Point { 5 | T x, y; 6 | }; 7 | 8 | template 9 | T Nevilles(std::vector> const& points, T x) { 10 | // interpolate a polynomial of degree points.size()-1, and evaluate it at x 11 | // let p[i][j](x) be the polynomial interpolated with the points i..j 12 | // then - p[i][i](x) = y_i 13 | // - p[i][j](x) = ((x - x_j) * p[i][j-1](x) - (x - x_i) * p[i+1][j](x)) / (x-i - x_j) 14 | int degree = points.size() - 1; 15 | std::vector p(degree + 1); 16 | for (int i = 0; i <= degree; i++) 17 | p[i] = points[i].y; 18 | for (int d = 1; d <= degree; d++) { 19 | for (int i = 0; i <= degree - d; i++) { 20 | int j = i + d; 21 | p[i] = ((x - points[j].x) * p[i] - (x - points[i].x) * p[i+1]) / (points[i].x - points[j].x); 22 | } 23 | } 24 | return p[0]; 25 | } 26 | -------------------------------------------------------------------------------- /Math/NevilleInterpolationPolynomial.h: -------------------------------------------------------------------------------- 1 | #include "SlowPolynomial.h" 2 | 3 | template 4 | struct Point { 5 | T x, y; 6 | }; 7 | 8 | template 9 | Polynomial Nevilles(std::vector> const& points) { 10 | // interpolate a polynomial of degree points.size()-1 11 | int degree = points.size() - 1; 12 | Polynomial x({0, 1}); 13 | std::vector> p(degree + 1); 14 | for (int i = 0; i <= degree; i++) 15 | p[i] = Polynomial({points[i].y}); 16 | for (int d = 1; d <= degree; d++) { 17 | for (int i = 0; i <= degree - d; i++) { 18 | int j = i + d; 19 | p[i] = (Polynomial({-points[j].x, 1}) * p[i] - Polynomial({-points[i].x, 1}) * p[i + 1]) / (points[i].x - points[j].x); 20 | } 21 | } 22 | return p[0]; 23 | } 24 | -------------------------------------------------------------------------------- /Math/Polynomial.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "FFT.h" 4 | 5 | template 6 | class Polynomial { 7 | public: 8 | Polynomial() : coeffs({}) {} 9 | 10 | Polynomial(std::vector coeffs) : coeffs(coeffs) {} 11 | 12 | Polynomial& operator+=(Polynomial const& other) { 13 | coeffs.resize(max(coeffs.size(), other.coeffs.size())); 14 | for (int i = 0; i < (int)other.coeffs.size(); i++) { 15 | coeffs[i] += other.coeffs[i]; 16 | } 17 | shorten(); 18 | return *this; 19 | } 20 | 21 | Polynomial operator+(Polynomial const& other) const { 22 | return Polynomial(*this) += other; 23 | } 24 | 25 | Polynomial& operator-=(Polynomial const& other) { 26 | coeffs.resize(max(coeffs.size(), other.coeffs.size())); 27 | for (int i = 0; i < (int)other.coeffs.size(); i++) { 28 | coeffs[i] -= other.coeffs[i]; 29 | } 30 | shorten(); 31 | return *this; 32 | } 33 | 34 | Polynomial operator-(Polynomial const& other) const { 35 | return Polynomial(*this) -= other; 36 | } 37 | 38 | Polynomial& operator*=(T const& x) { 39 | for (T& coeff : coeffs) 40 | coeff *= x; 41 | shorten(); 42 | return *this; 43 | } 44 | 45 | Polynomial operator*(T const& x) const { 46 | return Polynomial(*this) *= x; 47 | } 48 | 49 | Polynomial& operator*=(Polynomial const& other) { 50 | if (coeffs.empty() || other.coeffs.empty()) { 51 | coeffs.clear(); 52 | return *this; 53 | } 54 | 55 | int result_deg = deg() + other.deg() - 1; 56 | if (result_deg <= 200) { 57 | coeffs = multiply_brute_force(coeffs, other.coeffs, result_deg); 58 | } else { 59 | coeffs = fft_multiply(coeffs, other.coeffs); 60 | } 61 | shorten(); 62 | return *this; 63 | } 64 | 65 | Polynomial operator*(Polynomial const& other) const { 66 | return Polynomial(*this) *= other; 67 | } 68 | 69 | Polynomial& operator/=(T const& x) { 70 | return *this *= T(1) / x; 71 | } 72 | 73 | Polynomial operator/(T const& x) const { 74 | return Polynomial(*this) /= x; 75 | } 76 | 77 | Polynomial operator/(Polynomial const& other) const { 78 | return divide(other).first; 79 | } 80 | 81 | Polynomial& operator/=(Polynomial const& other) { 82 | auto res = divide(other).first; 83 | coeffs.swap(res.coeffs); 84 | return *this; 85 | } 86 | 87 | Polynomial operator%(Polynomial const& other) const { 88 | return divide(other).second; 89 | } 90 | 91 | Polynomial& operator%=(Polynomial const& other) { 92 | auto res = divide(other).second; 93 | coeffs.swap(res.coeffs); 94 | return *this; 95 | } 96 | 97 | T evaluate(T const& x) const { // Horner's method 98 | T res(0); 99 | for (int i = (int)coeffs.size() - 1; i >= 0; i--) 100 | res = res * x + coeffs[i]; 101 | return res; 102 | } 103 | 104 | T operator()(T const& x) const { 105 | return evaluate(x); 106 | } 107 | 108 | Polynomial derivation() const { 109 | auto cpy = coeffs; 110 | for (int i = 1; i < (int)cpy.size(); i++) { 111 | cpy[i-1] = cpy[i] * i; 112 | } 113 | cpy.pop_back(); 114 | return Polynomial(cpy); 115 | } 116 | 117 | /** 118 | * Computes the poloynomial modulo x^n (so just the first n coefficitiens) 119 | */ 120 | Polynomial operator%(int n) const { 121 | if ((int)coeffs.size() <= n) 122 | return *this; 123 | Polynomial ret({coeffs.begin(), coeffs.begin() + n}); 124 | ret.shorten(); 125 | return ret; 126 | } 127 | 128 | /** 129 | * Compute the product of the linear factors (x - r[0]) * (x - r[1]) * ... 130 | * using binary splitting in O(n log(n)^2) 131 | */ 132 | static Polynomial linear_factors_product(std::vector const& r) { 133 | if ((int)r.size() == 0) 134 | return Polynomial({1}); 135 | return linear_factors_product(r, 0, r.size()); 136 | } 137 | 138 | /** 139 | * Evaluate the polynomial at multiple points in O(n log(n)^2) 140 | */ 141 | std::vector multi_point_evaluation(std::vector const& x) { 142 | int n = x.size(); 143 | if (n == 0) 144 | return {}; 145 | std::vector> tree(4*n); 146 | linear_factors_product(x, tree, 1, 0, n); 147 | return multi_point_evaluation(x, tree, 1, 0, n); 148 | } 149 | 150 | /** 151 | * Degree of the polynomial (acutally degree + 1, with deg = 0 for the 0 polynomial) 152 | */ 153 | int deg() const { 154 | return coeffs.size(); 155 | } 156 | 157 | friend std::ostream& operator<<(std::ostream& os, Polynomial const& p) { 158 | for (int i = (int)p.coeffs.size() - 1; i >= 0; i--) { 159 | os << p.coeffs[i]; 160 | if (i) 161 | os << "*x"; 162 | if (i > 1) 163 | os << "^" << i; 164 | if (i) 165 | os << " + "; 166 | } 167 | return os; 168 | } 169 | 170 | /** 171 | * Computes the reciprocal polynomial modulo x^n in O(n log(n)) 172 | */ 173 | Polynomial reciprocal(int n) const { 174 | assert(coeffs.size() && coeffs[0] != 0); 175 | int sz = 1; 176 | Polynomial R({T(1) / coeffs[0]}); 177 | while (sz < n) { 178 | // trick from adamant 179 | auto C = (R * (*this % (3 * sz))).substr(sz, 2 * sz); 180 | R -= (R * C % sz) << sz; 181 | sz *= 2; 182 | } 183 | return R % n; 184 | } 185 | 186 | void shorten() { 187 | while (coeffs.size() > 0 && coeffs.back() == 0) 188 | coeffs.pop_back(); 189 | } 190 | 191 | std::vector coeffs; 192 | // order of coefficients is small to large 193 | 194 | private: 195 | std::vector multiply_brute_force(std::vector const& a, std::vector const& b, int sz) { 196 | std::vector result(sz); 197 | for (int i = 0; i < (int)a.size(); i++) { 198 | for (int j = 0; j < (int)b.size(); j++) { 199 | result[i + j] += (T)a[i] * b[j]; 200 | } 201 | } 202 | return result; 203 | } 204 | 205 | /** 206 | * extracts the coefficients from l to r 207 | */ 208 | Polynomial substr(int l, int r) const { 209 | l = std::min(l, (int)coeffs.size()); 210 | r = std::min(r, (int)coeffs.size()); 211 | return Polynomial(std::vector(coeffs.begin() + l, coeffs.begin() + r)); 212 | } 213 | 214 | /** 215 | * multiplies the polynomial with x^n 216 | */ 217 | Polynomial operator<<(int n) const { 218 | auto cpy = *this; 219 | if (cpy.coeffs.size()) 220 | cpy.coeffs.insert(cpy.coeffs.begin(), n, T(0)); 221 | return cpy; 222 | } 223 | 224 | /** 225 | * reverse the coefficients of the polynomial 226 | */ 227 | Polynomial rev() const { 228 | Polynomial ret({coeffs.rbegin(), coeffs.rend()}); 229 | ret.shorten(); 230 | return ret; 231 | } 232 | 233 | /** 234 | * divide this polynomial by g in O(n log(n)) 235 | * returns quotient and remainder 236 | */ 237 | std::pair, Polynomial> divide(Polynomial const& g) const { 238 | assert(g.coeffs.size() > 0); 239 | if (deg() < g.deg()) 240 | return {Polynomial(), *this}; 241 | int n = deg() - g.deg() + 1; 242 | if (min(n, g.deg()) < 500) 243 | return divide_brute_force(g); 244 | 245 | auto quotient = ((rev() % n) * (g.rev() % n).reciprocal(n) % n).rev(); 246 | // fill if too short 247 | quotient = quotient << (n - quotient.coeffs.size()); 248 | return {quotient, *this - quotient * g}; 249 | } 250 | 251 | /** 252 | * Normal division from school 253 | * returns quotient and remainder 254 | */ 255 | std::pair, Polynomial> divide_brute_force(Polynomial const& g) const { 256 | std::vector divident(coeffs); 257 | const auto& divisor = g.coeffs; 258 | std::vector quotient; 259 | quotient.reserve(divident.size() - divisor.size() + 1); 260 | while (divident.size() >= divisor.size()) { 261 | T q = divident.back() / divisor.back(); 262 | quotient.push_back(q); 263 | for (int i = 0; i < (int)divisor.size(); i++) { 264 | divident[divident.size() - i - 1] -= q * divisor[divisor.size() - i - 1]; 265 | } 266 | divident.pop_back(); 267 | } 268 | std::reverse(quotient.begin(), quotient.end()); 269 | return {Polynomial(quotient), Polynomial(divident)}; 270 | } 271 | 272 | /** 273 | * Compute the product of the linear factors (x - r[0]) * (x - r[1]) * ... 274 | * using binary splitting in O(n log(n)^2) 275 | */ 276 | static Polynomial linear_factors_product(std::vector const& roots, int l, int r) { 277 | if (l + 1 == r) 278 | return Polynomial({-roots[l], 1}); 279 | int m = (l + r) / 2; 280 | return linear_factors_product(roots, l, m) * linear_factors_product(roots, m, r); 281 | } 282 | 283 | /** 284 | * Compute the product of the linear factors (x - r[0]) * (x - r[1]) * ... 285 | * using binary splitting in O(n log(n)^2) and store the tree 286 | */ 287 | static Polynomial linear_factors_product(std::vector const& roots, std::vector>& tree, int v, int l, int r) { 288 | if (l + 1 == r) 289 | return tree[v] = Polynomial({-roots[l], 1}); 290 | int m = (l + r) / 2; 291 | return tree[v] = linear_factors_product(roots, tree, 2*v, l, m) * linear_factors_product(roots, tree, 2*v+1, m, r); 292 | } 293 | 294 | /** 295 | * Compute the product of the linear factors (x - r[0]) * (x - r[1]) * ... 296 | * using binary splitting in O(n log(n)^2) and store the tree 297 | */ 298 | std::vector multi_point_evaluation(std::vector const& x, std::vector> const& tree, int v, int l, int r) const { 299 | if (l + 1 == r) 300 | return {evaluate(x[l])}; 301 | 302 | int m = (l + r) / 2; 303 | std::vector res1 = (*this % tree[2*v]).multi_point_evaluation(x, tree, 2*v, l, m); 304 | auto res2 = (*this % tree[2*v+1]).multi_point_evaluation(x, tree, 2*v+1, m, r); 305 | res1.insert(res1.end(), res2.begin(), res2.end()); 306 | return res1; 307 | } 308 | }; 309 | 310 | /** 311 | * Computes the determinant of the Vandermonde Matrix 312 | * This is equivalent to the product Π_{i!=j} (a_j - a_i) 313 | * or the square of Π_{i 316 | T VandermondeDeterminant(std::vector const& v) { 317 | auto P = Polynomial::linear_factors_product(v); 318 | auto evaled = P.derivation().multi_point_evaluation(v); 319 | 320 | T prod(1); 321 | for (auto x : evaled) 322 | prod *= x; 323 | int n = v.size(); 324 | if ((long long)n * (n - 1) / 2 % 2) 325 | prod *= -1; 326 | return prod; 327 | } 328 | -------------------------------------------------------------------------------- /Math/PowerSums.h: -------------------------------------------------------------------------------- 1 | #include "SlowPolynomial.h" 2 | #include "NevilleInterpolationPolynomial.h" 3 | 4 | template 5 | Polynomial compute_power_sum_polynomial(int exp) { 6 | std::vector> points; 7 | int req = exp + 2; 8 | T sum = 0; 9 | for (int j = 0; j < req; j++) { 10 | sum += power(T(j), exp); 11 | points.push_back({j, sum}); 12 | } 13 | return Nevilles(points); 14 | } 15 | -------------------------------------------------------------------------------- /Math/PrimeLargest.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void computePrimesLargest(int n, std::vector &largest) 5 | { 6 | largest.resize(n + 1); 7 | std::iota(largest.begin(), largest.end(), 0); 8 | 9 | for (int i = 2; i <= n; i++) { 10 | if (i == largest[i]) { 11 | for (int j = 2 * i; j <= n; j += i) { 12 | largest[j] = i; 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Math/Primes.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::vector compute_primes(int n) { 5 | const int S = 30000; 6 | int nsqrt = std::round(std::sqrt(n)); 7 | 8 | std::vector is_prime(nsqrt + 1, true); 9 | std::vector primes, sieve_primes, start_indices; 10 | for (int i = 3; i <= nsqrt; i += 2) { 11 | if (is_prime[i]) { 12 | sieve_primes.push_back(i); 13 | start_indices.push_back((i * i - 1) / 2); 14 | for (int j = i * i; j <= nsqrt; j += 2 * i) 15 | is_prime[j] = false; 16 | } 17 | } 18 | 19 | primes.push_back(2); 20 | std::vector block(S); 21 | int high = (n - 1) / 2; 22 | for (int low = 0; low <= high; low += S) { 23 | fill(block.begin(), block.end(), true); 24 | for (auto i = 0u; i < sieve_primes.size(); i++) { 25 | int p = sieve_primes[i]; 26 | int idx = start_indices[i]; 27 | for (; idx < S; idx += p) 28 | block[idx] = false; 29 | start_indices[i] = idx - S; 30 | } 31 | if (low == 0) 32 | block[0] = false; 33 | for (int i = 0; i < S && low + i <= high; i++) { 34 | if (block[i]) 35 | primes.push_back((low + i) * 2 + 1); 36 | } 37 | }; 38 | 39 | return primes; 40 | } 41 | -------------------------------------------------------------------------------- /Math/RankBitset.h: -------------------------------------------------------------------------------- 1 | #include "../Other/Bitset.h" 2 | 3 | int compute_rank(std::vector bitsets) { 4 | int rank = 0; 5 | for (int i = 0; i < (int)bitsets.size(); i++) { 6 | int idx = bitsets[i].first_set(); 7 | if (idx == -1) 8 | break; 9 | rank++; 10 | for (int j = i + 1; j < (int)bitsets.size(); j++) { 11 | if (bitsets[j].check(idx)) 12 | bitsets[j] ^= bitsets[i]; 13 | } 14 | } 15 | return rank; 16 | } 17 | -------------------------------------------------------------------------------- /Math/Rho.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "MillerRabin.h" 6 | 7 | long long mult(long long a, long long b, long long m) { 8 | return (__uint128_t)a * b % m; 9 | } 10 | 11 | long long f(long long x, long long c, long long m) { 12 | long long ret = mult(x, x, m) + c; 13 | if (ret >= m) 14 | ret -= m; 15 | return ret; 16 | } 17 | 18 | long long brent(long long n, long long x0=2, long long c=1) { 19 | long long x = x0; 20 | long long g = 1; 21 | long long q = 1; 22 | long long xs, y; 23 | 24 | int m = 128; 25 | int l = 1; 26 | while (g == 1) { 27 | y = x; 28 | for (int i = 1; i < l; i++) 29 | x = f(x, c, n); 30 | int k = 0; 31 | while (k < l && g == 1) { 32 | xs = x; 33 | for (int i = 0; i < m && i < l - k; i++) { 34 | x = f(x, c, n); 35 | q = mult(q, std::abs(y - x), n); 36 | } 37 | g = std::gcd(q, n); 38 | k += m; 39 | } 40 | l *= 2; 41 | } 42 | if (g == n) { 43 | do { 44 | xs = f(xs, c, n); 45 | g = std::gcd(std::abs(xs - y), n); 46 | } while (g == 1); 47 | } 48 | return g; 49 | } 50 | 51 | class Factorizer { 52 | public: 53 | std::vector factorize(long long x) { 54 | factors.clear(); 55 | 56 | static std::vector primes_100 = 57 | {2, 3, 5, 7, 11, 13, 17, 19, 23, 58 | 29, 31, 37, 41, 43, 47, 53, 59, 59 | 61, 67, 71, 73, 79, 83, 89, 97}; 60 | for (int p : primes_100) { 61 | while (x % p == 0) { 62 | factors.push_back(p); 63 | x /= p; 64 | } 65 | } 66 | 67 | recursive_factorize(x); 68 | sort(factors.begin(), factors.end()); 69 | return factors; 70 | } 71 | 72 | void recursive_factorize(long long x) { 73 | if (x < 100 * 100 || MillerRabin(x)) { 74 | factors.push_back(x); 75 | } else { 76 | int c = 1; 77 | long long g = x; 78 | while (g == x) { 79 | g = brent(x, 2, ++c); 80 | } 81 | recursive_factorize(g); 82 | recursive_factorize(x / g); 83 | } 84 | } 85 | 86 | private: 87 | std::vector factors; 88 | }; 89 | -------------------------------------------------------------------------------- /Math/SlowPolynomial.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | class Polynomial { 6 | public: 7 | Polynomial() : coeffs({}) {} 8 | Polynomial(std::vector coeffs) : coeffs(coeffs) {} 9 | 10 | Polynomial& operator+=(Polynomial const& other) { 11 | coeffs.resize(max(coeffs.size(), other.coeffs.size())); 12 | for (int i = 0; i < coeffs.size(); i++) { 13 | coeffs[i] += other.coeffs[i]; 14 | } 15 | shorten(); 16 | return *this; 17 | } 18 | Polynomial operator+(Polynomial const& other) { 19 | return Polynomial(*this) += other; 20 | } 21 | Polynomial& operator-=(Polynomial const& other) { 22 | coeffs.resize(max(coeffs.size(), other.coeffs.size())); 23 | for (int i = 0; i < coeffs.size(); i++) { 24 | coeffs[i] -= other.coeffs[i]; 25 | } 26 | shorten(); 27 | return *this; 28 | } 29 | Polynomial operator-(Polynomial const& other) { 30 | return Polynomial(*this) -= other; 31 | } 32 | Polynomial& operator*=(T const& x) { 33 | for (T& coeff : coeffs) 34 | coeff *= x; 35 | shorten(); 36 | return *this; 37 | } 38 | Polynomial operator*(T const& x) { 39 | return Polynomial(*this) *= x; 40 | } 41 | Polynomial& operator/=(T const& x) { 42 | return *this *= (1 / x); 43 | } 44 | Polynomial operator/(T const& x) { 45 | return Polynomial(*this) /= x; 46 | } 47 | Polynomial& operator*=(Polynomial const& other) { 48 | std::vector new_coeffs(coeffs.size() + other.coeffs.size() - 1, 0); 49 | for (int i = 0; i < coeffs.size(); i++) { 50 | for (int j = 0; j < other.coeffs.size(); j++) { 51 | new_coeffs[i+j] += coeffs[i] * other.coeffs[j]; 52 | } 53 | } 54 | coeffs.swap(new_coeffs); 55 | shorten(); 56 | return *this; 57 | } 58 | Polynomial operator*(Polynomial const& other) { 59 | return Polynomial(*this) *= other; 60 | } 61 | 62 | T evaluate(T const& x) { // Horner's method 63 | T res = 0; 64 | for (int i = coeffs.size() - 1; i >= 0; i--) 65 | res = res * x + coeffs[i]; 66 | return res; 67 | } 68 | 69 | friend std::ostream& operator<<(std::ostream& os, Polynomial const& p) { 70 | for (int i = p.coeffs.size() - 1; i >= 0; i--) { 71 | os << p.coeffs[i]; 72 | if (i) 73 | os << "*x"; 74 | if (i > 1) 75 | os << "^" << i; 76 | if (i) 77 | os << " + "; 78 | } 79 | return os; 80 | } 81 | void shorten() { 82 | while (coeffs.back() == 0 && coeffs.size() > 1) 83 | coeffs.pop_back(); 84 | } 85 | 86 | std::vector coeffs; 87 | // order of coefficients is small to large 88 | }; 89 | -------------------------------------------------------------------------------- /Math/SquareRoot.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int sqrt(long long x) { 4 | long long L = 0; 5 | long long R = std::numeric_limits::max(); 6 | while (L + 1 < R) { 7 | long long M = (L + R) / 2; 8 | if (M * M <= x) 9 | L = M; 10 | else 11 | R = M; 12 | } 13 | return L; 14 | } 15 | -------------------------------------------------------------------------------- /Math/SternBrocotSmallestBetween.h: -------------------------------------------------------------------------------- 1 | #include "Fraction.h" 2 | 3 | Fraction mediant(Fraction const& f, Fraction const& g, int wf=1, int wg=1) { 4 | return {f.a*wf + g.a*wg, f.b*wf + g.b*wg}; 5 | } 6 | 7 | Fraction find_smallest_between(Fraction const& L, Fraction const& R) { 8 | Fraction l(0, 1), r(1, 0); 9 | 10 | while (true) { 11 | Fraction m = mediant(l, r); 12 | if (m <= L) { // move left border to the right, but don't overshoot 13 | long long bl = 0, br = 1; 14 | while (mediant(l, r, 1, br) <= L) 15 | br *= 2; 16 | while (bl + 1 != br) { 17 | long long bm = (bl + br) / 2; 18 | if (mediant(l, r, 1, bm) <= L) 19 | bl = bm; 20 | else 21 | br = bm; 22 | } 23 | l = mediant(l, r, 1, bl); 24 | } else if (m >= R) { // move right border to the left, but don't overshoot 25 | long long bl = 0, br = 1; 26 | while (mediant(l, r, br, 1) >= R) 27 | br *= 2; 28 | while (bl + 1 != br) { 29 | long long bm = (bl + br) / 2; 30 | if (mediant(l, r, bm, 1) >= R) 31 | bl = bm; 32 | else 33 | br = bm; 34 | } 35 | r = mediant(l, r, bl, 1); 36 | } else { 37 | return m; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Math/Stirling2nd.h: -------------------------------------------------------------------------------- 1 | #include "FastBinomialCoefficient.h" 2 | 3 | ModInt Stirling2nd(int n, int k) { 4 | ModInt res; 5 | for (int j = 0; j <= k; j++) { 6 | ModInt x = Binomial(k, j) * power(ModInt(j), n); 7 | if ((k - j) & 1) 8 | res -= x; 9 | else 10 | res += x; 11 | } 12 | return res * f_inv[k]; 13 | } 14 | -------------------------------------------------------------------------------- /Math/Totient.h: -------------------------------------------------------------------------------- 1 | int totient(int num) 2 | { 3 | int res = num; 4 | for (int div = 2; div * div <= num; div++) { 5 | if (num % div == 0) { 6 | res /= div; 7 | res *= div - 1; 8 | while (num % div == 0) { 9 | num /= div; 10 | } 11 | } 12 | } 13 | if (num > 1) { 14 | res /= num; 15 | res *= num - 1; 16 | } 17 | return res; 18 | } 19 | -------------------------------------------------------------------------------- /Math/TotientSieve.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PrimeLargest.h" 3 | 4 | std::vector largest; 5 | 6 | int totient(int num) 7 | { 8 | int coprime = 1; 9 | while (num > 1) { 10 | int l = largest[num]; 11 | num /= l; 12 | int p = 1; 13 | while (largest[num] == l) { 14 | num /= l; 15 | p *= l; 16 | } 17 | coprime *= p * (l - 1); 18 | } 19 | return coprime; 20 | } 21 | 22 | int main() 23 | { 24 | computePrimesLargest(1e7, largest); 25 | std::cout << totient(99) << std::endl; 26 | } 27 | -------------------------------------------------------------------------------- /Math/moebius.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void compute_moebius(int n, std::vector &moebius) 4 | { 5 | moebius.assign(n + 1, 2); 6 | std::vector divisors(n + 1, 0); 7 | 8 | for (int i = 2; i <= n; i++) { 9 | if (divisors[i] == 0) { 10 | for (int j = 1, jm = 1; j * i <= n; j++, jm++) { 11 | if (jm == i) { 12 | jm = 0; 13 | moebius[j*i] = 0; 14 | } 15 | divisors[j*i]++; 16 | } 17 | } 18 | } 19 | 20 | for (int i = 0; i <= n; i++) { 21 | if (moebius[i] == 2) 22 | moebius[i] = (divisors[i] & 1) ? -1 : 1; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Other/Bitset.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Bitset { 4 | public: 5 | Bitset(int n=0) : data((n + 63)/64) {} 6 | Bitset(Bitset const& o) : data(o.data) {} 7 | 8 | Bitset& operator^=(Bitset const& o) { 9 | for (auto i = 0u; i < data.size(); i++) 10 | data[i] ^= o.data[i]; 11 | return *this; 12 | } 13 | 14 | bool check(int idx) const { 15 | return data[idx/64] & (1LL << (idx%64)); 16 | } 17 | 18 | void set(int idx) { 19 | data[idx/64] |= (1LL << (idx%64)); 20 | } 21 | 22 | int first_set() const { 23 | for (auto i = 0u; i < data.size(); i++) { 24 | if (data[i] == 0) 25 | continue; 26 | int idx = 64 * i; 27 | auto bits = data[i]; 28 | while (!(bits & 1)) { 29 | idx++; 30 | bits >>= 1; 31 | } 32 | return idx; 33 | } 34 | return -1; 35 | } 36 | 37 | private: 38 | std::vector data; 39 | }; 40 | -------------------------------------------------------------------------------- /Other/MonotoneStorage.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class MonotoneStorage { 5 | public: 6 | void insert(T x, S y) { 7 | auto it = storage.upper_bound(x); 8 | if (it != storage.begin()) { 9 | auto prev = it; 10 | --prev; 11 | if (prev->second >= y) 12 | return; 13 | if (it->first == x) 14 | it = prev; 15 | } 16 | 17 | auto ti = it; 18 | while (ti != storage.end() && y >= ti->second) 19 | ++ti; 20 | 21 | storage.erase(it, ti); 22 | storage[x] = y; 23 | } 24 | 25 | S max_upto(T x) { 26 | auto it = storage.upper_bound(x); 27 | if (it == storage.begin()) 28 | return 0; 29 | --it; 30 | return it->second; 31 | } 32 | 33 | private: 34 | std::map storage; 35 | }; 36 | -------------------------------------------------------------------------------- /Other/SegmentSet.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct Segment { 6 | int l, r; 7 | 8 | bool operator<(Segment const& other) const { 9 | return l < other.l; 10 | } 11 | 12 | int overlap(Segment const& o) const { 13 | return std::max(0, std::min(r, o.r) - std::max(l, o.l)); 14 | } 15 | 16 | bool touch(Segment const& o) const { 17 | return overlap(o) || o.r == l || o.l == r; 18 | } 19 | 20 | Segment Union(Segment const o) const { 21 | return {std::min(l, o.l), std::max(r, o.r)}; 22 | } 23 | 24 | friend std::ostream& operator<<(std::ostream& os, Segment const& s) { 25 | return os << "[" << s.l << ", " << s.r << "]"; 26 | } 27 | 28 | friend std::istream& operator>>(std::istream& is, Segment& s) { 29 | return is >> s.l >> s.r; 30 | } 31 | }; 32 | 33 | /** 34 | * Set containing segements 35 | * If two segments overlap or touch (depending on settings), they will be replaced by their union. 36 | */ 37 | class DisjointSegmentSet { 38 | public: 39 | DisjointSegmentSet(bool touching=true) : touching(touching) {} 40 | using It = std::set::iterator; 41 | using ItRange = std::pair; 42 | 43 | /** 44 | * add a segment to the set, union with overlapping/touching segments 45 | */ 46 | void add_segment(Segment s) { 47 | auto [lit, rit] = get_overlapping_or_touching(s); 48 | for (It it = lit; it != rit; ++it) { 49 | auto& t = *it; 50 | s = s.Union(t); 51 | } 52 | segments.erase(lit, rit); 53 | segments.insert(s); 54 | } 55 | 56 | /** 57 | * remove a segment from the set, return the overlaps 58 | */ 59 | std::vector subtract(Segment s) { 60 | split(s.l); 61 | split(s.r); 62 | auto [lit, rit] = get_overlapping(s); 63 | std::vector ret(lit, rit); 64 | segments.erase(lit, rit); 65 | return ret; 66 | } 67 | 68 | /** 69 | * Find a segment that contains x 70 | * In case of two segments touching at x, it will find the left one 71 | */ 72 | It find_containing(int x) const { 73 | It lit = segments.lower_bound({x, 0}); 74 | if (lit != segments.begin()) { 75 | --lit; 76 | if (lit->r < x) 77 | ++lit; 78 | } 79 | return lit; 80 | } 81 | 82 | friend std::ostream& operator<<(std::ostream& os, DisjointSegmentSet const& dss) { 83 | os << "DSS("; 84 | auto bit = dss.segments.begin(); 85 | for (auto it = bit; it != dss.segments.end(); ++it) { 86 | if (it != bit) 87 | os << ", "; 88 | os << *it; 89 | } 90 | return os << ")"; 91 | } 92 | 93 | private: 94 | ItRange get_overlapping_or_touching(Segment const& s) const { 95 | // find smallest segment with l >= s.l 96 | auto lit = touching ? segments.lower_bound(s) : segments.upper_bound(s); 97 | // it's possible that there is one the left 98 | if (lit != segments.begin()) { 99 | --lit; 100 | if (touching && lit->r < s.l) 101 | ++lit; 102 | if (!touching && lit->r <= s.l) 103 | ++lit; 104 | } 105 | 106 | // find right boundary 107 | auto rit = touching ? segments.upper_bound({s.r, 0}) : segments.lower_bound({s.r, 0}); 108 | 109 | return {lit, rit}; 110 | } 111 | 112 | void split(int x) { 113 | auto it = find_containing(x); 114 | if (it == segments.end()) 115 | return; 116 | auto s = *it; 117 | if (s.l < x && x < s.r) { 118 | segments.erase(it); 119 | auto s1 = s; 120 | s1.r = x; 121 | auto s2 = s; 122 | s2.l = x; 123 | segments.insert(s1); 124 | segments.insert(s2); 125 | } 126 | } 127 | 128 | bool touching; 129 | std::set segments; 130 | }; 131 | -------------------------------------------------------------------------------- /Other/TwoColorPartition.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Interval 4 | { 5 | int l, r, color; 6 | bool operator<(const Interval& o) const { 7 | return l < o.l; 8 | } 9 | }; 10 | 11 | class TwoColorPartition 12 | { 13 | public: 14 | TwoColorPartition(int n) { 15 | s.insert({0, n-1, 0}); 16 | } 17 | 18 | using It = std::set::iterator; 19 | 20 | void split(int x) { 21 | // x becomes the left border of interval 22 | auto it = s.upper_bound({x, 0, 0}); 23 | --it; 24 | if (it->l < x) { 25 | auto I = *it; 26 | s.erase(it); 27 | s.insert({I.l, x-1, I.color}); 28 | s.insert({x, I.r, I.color}); 29 | } 30 | } 31 | 32 | std::pair get_iterators(int l, int r) { 33 | split(l); 34 | split(r+1); 35 | return {s.lower_bound({l, 0, 0}), s.upper_bound({r, 0, 0})}; 36 | } 37 | 38 | void color(It lit, It rit, int c) { 39 | int l = lit->l; 40 | auto tmp = rit; 41 | --tmp; 42 | int r = tmp->r; 43 | s.erase(lit, rit); 44 | s.insert({l, r, c}); 45 | } 46 | 47 | private: 48 | std::set s; 49 | }; 50 | -------------------------------------------------------------------------------- /Other/VeniceSet.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct VeniceSet { 5 | std::multiset s; 6 | T water_level = 0; 7 | 8 | void add(T v) { 9 | s.insert(v + water_level); 10 | } 11 | 12 | void remove(T v) { 13 | s.erase(s.find(v + water_level)); 14 | } 15 | 16 | void decrease_all(T v) { 17 | water_level += v; 18 | } 19 | 20 | T min() const { 21 | return *s.begin() - water_level; 22 | } 23 | 24 | int size() const { 25 | return s.size(); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithm-DataStructures 2 | 3 | Implementations of common algorithms and data structures used for competitive programming. 4 | 5 | ## Vim plugin 6 | 7 | The algorithms and data structures can easily be pasted into a document using the included Vim plugin. 8 | 9 | ![demonstration](demonstration.gif) 10 | 11 | ### Installation 12 | 13 | Use [vim-plug](https://github.com/junegunn/vim-plug) or any Vim plugin manager of your choice. 14 | The plugin [fzf](https://github.com/junegunn/fzf) is a requirement. 15 | 16 | With vim-plug: 17 | 18 | ```vim 19 | Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' } 20 | Plug 'jakobkogler/Algorithm-DataStructures' 21 | ``` 22 | 23 | ### Command/Usage 24 | 25 | The plugin defines a single command `AlgDS`. 26 | It can be mapped like this: 27 | 28 | ```vim 29 | nmap alg :AlgDS 30 | ``` 31 | 32 | ## Pretty Printer 33 | 34 | There are some pretty printer for GDB. 35 | You can activate them by putting the following in your `~/.gdbinit`: 36 | 37 | ```sh 38 | source ~/.vim/plugged/Algorithm-DataStructures/prettyprint.py 39 | ``` 40 | 41 | ## License 42 | 43 | WTFPL 44 | -------------------------------------------------------------------------------- /RangeQuery/BIT.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class BIT { 5 | // Implementation of a Binary Indexed Tree (Fennwick Tree) 6 | public: 7 | BIT(int n) : n(n + 1) { 8 | m_array = std::vector(this->n, 0); 9 | } 10 | 11 | BIT(const std::vector& list) { 12 | // Initialize BIT with list in O(n) 13 | m_array = std::vector(n, 0); 14 | std::copy(list.begin(), list.end(), m_array.begin() + 1); 15 | 16 | for (int idx = 1; idx < n; idx++) { 17 | int idx2 = idx + (idx & -idx); 18 | if (idx2 < n) { 19 | m_array[idx2] += m_array[idx]; 20 | } 21 | } 22 | } 23 | 24 | // Computes sum of the range [0, idx) 25 | int prefix_query(int idx) { 26 | int result = 0; 27 | for (; idx > 0; idx -= idx & -idx) { 28 | result += m_array[idx]; 29 | } 30 | return result; 31 | } 32 | 33 | // Computes the range sum of the range [l, r) 34 | int range_query(int l, int r) { 35 | return prefix_query(r) - prefix_query(l); 36 | } 37 | 38 | // Add a value to the idx-th element 39 | void update(int idx, int add) { 40 | for (++idx; idx < n; idx += idx & -idx) { 41 | m_array[idx] += add; 42 | } 43 | } 44 | 45 | private: 46 | std::vector m_array; 47 | int n; 48 | }; 49 | -------------------------------------------------------------------------------- /RangeQuery/BIT_Range_Updates.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class BIT_Range_Updates { 5 | public: 6 | BIT_Range_Updates(int n) : n(n + 1) { 7 | m_array.resize(n + 1, 0); 8 | } 9 | 10 | BIT_Range_Updates(const std::vector& list) : n(list.size() + 1) { 11 | n = list.size() + 1; 12 | m_array = std::vector(n, 0); 13 | for (int i = 0; i < n; i++) 14 | m_array[i+1] = list[i] - (i > 0 ? list[i-1] : 0); 15 | 16 | for (int idx = 1; idx < n; idx++) { 17 | int idx2 = idx + (idx & -idx); 18 | if (idx2 < (int)m_array.size()) { 19 | m_array[idx2] += m_array[idx]; 20 | } 21 | } 22 | } 23 | 24 | T value(int idx) { 25 | T result = 0; 26 | for (++idx; idx > 0; idx -= idx & -idx) 27 | result += m_array[idx]; 28 | return result; 29 | } 30 | 31 | // add x to the range [l, r) 32 | void range_add(int l, int r, T x) { 33 | suffix_add(l, x); 34 | suffix_add(r, -x); 35 | } 36 | 37 | // add x to the suffix starting at index idx 38 | void suffix_add(int idx, T add) { 39 | for (++idx; idx < n; idx += idx & -idx) 40 | m_array[idx] += add; 41 | } 42 | 43 | private: 44 | std::vector m_array; 45 | int n; 46 | }; 47 | -------------------------------------------------------------------------------- /RangeQuery/BinaryIndexedTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | class BIT { 7 | // Implementation of a Binary Indexed Tree (Fennwick Tree) 8 | public: 9 | /*BIT(std::vector list) { 10 | // Initialize BIT with list in O(n*log(n)) 11 | m_array = std::vector(list.size() + 1, 0); 12 | for (int idx = 0; idx < list.size(); idx++) { 13 | update(idx, list[idx]); 14 | } 15 | }*/ 16 | 17 | BIT(std::vector list) { 18 | // Initialize BIT with list in O(n) 19 | m_array = std::vector(list.size() + 1, 0); 20 | for (int idx = 0; idx < list.size(); idx++) { 21 | m_array[idx + 1] = list[idx]; 22 | } 23 | 24 | for (int idx = 1; idx < m_array.size(); idx++) { 25 | int idx2 = idx + (idx & -idx); 26 | if (idx2 < m_array.size()) { 27 | m_array[idx2] += m_array[idx]; 28 | } 29 | } 30 | } 31 | 32 | int prefix_query(int idx) const { 33 | // Computes prefix sum of up to the element at index idx 34 | int result = 0; 35 | for (++idx; idx > 0; idx -= idx & -idx) { 36 | result += m_array[idx]; 37 | } 38 | return result; 39 | } 40 | 41 | int range_query(int from_idx, int to_idx) const { 42 | // Computes the range sum between two indices (both inclusive) 43 | if (from_idx == 0) 44 | return prefix_query(to_idx); 45 | else 46 | return prefix_query(to_idx) - prefix_query(from_idx - 1); 47 | } 48 | 49 | void update(int idx, int add) { 50 | // Add a value to the element at index idx 51 | for (++idx; idx < m_array.size(); idx += idx & -idx) { 52 | m_array[idx] += add; 53 | } 54 | } 55 | 56 | private: 57 | std::vector m_array; 58 | }; 59 | 60 | void print(BIT const& bit, int length) { 61 | std::cout << "Index: "; 62 | for (int idx = 0; idx < length; ++idx) 63 | std::cout << std::setw(2) << idx << " "; 64 | std::cout << std::endl; 65 | std::cout << "Array: "; 66 | for (int idx = 0; idx < length; ++idx) 67 | std::cout << std::setw(2) << bit.range_query(idx, idx) << " "; 68 | std::cout << std::endl << std::endl; 69 | 70 | std::cout << "Prefix sum of first 13 elements: \t" << bit.prefix_query(12) << std::endl; 71 | std::cout << "Prefix sum of first 7 elements: \t" << bit.prefix_query(6) << std::endl; 72 | std::cout << "Range sum from index 1 to index 5: \t" << bit.range_query(1, 5) << std::endl; 73 | std::cout << std::endl; 74 | } 75 | 76 | int main() 77 | { 78 | std::vector array{ 1, 7, 3, 0, 5, 8, 3, 2, 6, 2, 1, 1, 4, 5 }; 79 | int length = array.size(); 80 | BIT bit(array); 81 | print(bit, length); 82 | 83 | bit.update(4, 2); 84 | std::cout << "Add 2 to element at index 4" << std::endl << std::endl; 85 | print(bit, length); 86 | } 87 | -------------------------------------------------------------------------------- /RangeQuery/BinaryIndexedTree.py: -------------------------------------------------------------------------------- 1 | class BIT: 2 | """Implementation of a Binary Indexed Tree (Fennwick Tree)""" 3 | 4 | #def __init__(self, list): 5 | # """Initialize BIT with list in O(n*log(n))""" 6 | # self.array = [0] * (len(list) + 1) 7 | # for idx, val in enumerate(list): 8 | # self.update(idx, val) 9 | 10 | def __init__(self, list): 11 | """"Initialize BIT with list in O(n)""" 12 | self.array = [0] + list 13 | for idx in range(1, len(self.array)): 14 | idx2 = idx + (idx & -idx) 15 | if idx2 < len(self.array): 16 | self.array[idx2] += self.array[idx] 17 | 18 | def prefix_query(self, idx): 19 | """Computes prefix sum of up to including the idx-th element""" 20 | idx += 1 21 | result = 0 22 | while idx: 23 | result += self.array[idx] 24 | idx -= idx & -idx 25 | return result 26 | 27 | def range_query(self, from_idx, to_idx): 28 | """Computes the range sum between two indices (both inclusive)""" 29 | return self.prefix_query(to_idx) - self.prefix_query(from_idx - 1) 30 | 31 | def update(self, idx, add): 32 | """Add a value to the idx-th element""" 33 | idx += 1 34 | while idx < len(self.array): 35 | self.array[idx] += add 36 | idx += idx & -idx 37 | 38 | 39 | if __name__ == '__main__': 40 | array = [1, 7, 3, 0, 5, 8, 3, 2, 6, 2, 1, 1, 4, 5] 41 | bit = BIT(array) 42 | print('Array: [{}]'.format(', '.join(map(str, array)))) 43 | print() 44 | 45 | print('Prefix sum of first {} elements: {}'.format(13, bit.prefix_query(12))) 46 | print('Prefix sum of first {} elements: {}'.format(7, bit.prefix_query(6))) 47 | print('Range sum from pos {} to pos {}: {}'.format(1, 5, bit.range_query(1, 5))) 48 | print() 49 | 50 | bit.update(4, 2) 51 | print('Add {} to element at pos {}'.format(2, 4)) 52 | new_array = [bit.range_query(idx, idx) for idx in range(len(array))] 53 | print('Array: [{}]'.format(', '.join(map(str, new_array)))) 54 | print() 55 | 56 | print('Prefix sum of first {} elements: {}'.format(13, bit.prefix_query(12))) 57 | print('Prefix sum of first {} elements: {}'.format(7, bit.prefix_query(6))) 58 | print('Range sum from pos {} to pos {}: {}'.format(1, 5, bit.range_query(1, 5))) 59 | print() -------------------------------------------------------------------------------- /RangeQuery/HashingSegmentTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class HashingSegmentTree { 4 | public: 5 | HashingSegmentTree(int count, int p, int mod) { 6 | n = count; 7 | data.assign(2 * n, 0); 8 | data2.assign(2 * n, 0); 9 | powers.resize(n + 1); 10 | powers[0] = 1; 11 | _mod = mod; 12 | for (int i = 0; i < n; i++) { 13 | powers[i+1] = (long long)powers[i] * p % mod; 14 | } 15 | } 16 | 17 | void update(int _idx, int value) { 18 | int idx = _idx + n; 19 | data[idx] = value * (long long)powers[_idx] % _mod; 20 | data2[idx] = value; 21 | 22 | while (idx > 1) { 23 | idx /= 2; 24 | data[idx] = data[2 * idx] + data[2 * idx + 1]; 25 | if (data[idx] >= _mod) 26 | data[idx] -= _mod; 27 | data2[idx] = data2[2 * idx] + data2[2 * idx + 1]; 28 | } 29 | } 30 | 31 | int sum(int _left, int _right) { // interval [left, right) 32 | long long ret = 0; 33 | int left = _left + n; 34 | int right = _right + n; 35 | 36 | while (left < right) { 37 | if (left & 1) ret += data[left++]; 38 | if (right & 1) ret += data[--right]; 39 | left >>= 1; 40 | right >>= 1; 41 | } 42 | 43 | return ret % _mod * powers[n - _left] % _mod; 44 | } 45 | 46 | private: 47 | int n; 48 | int _mod; 49 | std::vector data, data2; 50 | std::vector powers; 51 | }; 52 | -------------------------------------------------------------------------------- /RangeQuery/ImplicitSegmentTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Node; 5 | 6 | std::deque cache; 7 | 8 | Node* fetch_new() { 9 | cache.emplace_back(); 10 | return &cache.back(); 11 | } 12 | 13 | Node* fetch_new(Node const& node) { 14 | cache.emplace_back(node); 15 | return &cache.back(); 16 | } 17 | 18 | 19 | class Node { 20 | public: 21 | Node(int x) : x(x) {} 22 | 23 | void update(int l, int r, int pos, int val) { 24 | if (l + 1 == r) { 25 | x = val; 26 | } else { 27 | int m = (l + r) / 2; 28 | if (pos < m) { 29 | if (left == nullptr) 30 | left = fetch_new(Node(0)); 31 | left->update(l, m, pos, val); 32 | } else { 33 | if (right == nullptr) 34 | right = fetch_new(Node(0)); 35 | right->update(m, r, pos, val); 36 | } 37 | x = 0; 38 | if (left) 39 | x = std::max(x, left->x); 40 | if (right) 41 | x = std::max(x, right->x); 42 | } 43 | } 44 | 45 | int maximum(int l, int r, int rl, int rr) { 46 | if (rr <= l || rl >= r) 47 | return 0; 48 | if (rl <= l && r <= rr) 49 | return x; 50 | int m = (l + r) / 2; 51 | int res = 0; 52 | if (left) 53 | res = std::max(res, left->maximum(l, m, rl, rr)); 54 | if (right) 55 | res = std::max(res, right->maximum(m, r, rl, rr)); 56 | return res; 57 | } 58 | 59 | int x; 60 | Node* left = nullptr; 61 | Node* right = nullptr; 62 | }; 63 | 64 | class ImplicitSegmentTree { 65 | public: 66 | ImplicitSegmentTree(int n) : n(n), root(fetch_new(Node(0))) {} 67 | 68 | void update(int pos, int val) { 69 | root->update(0, n, pos, val); 70 | } 71 | 72 | int maximum(int l, int r) { 73 | return root->maximum(0, n, l, r); 74 | } 75 | 76 | private: 77 | int n; 78 | Node* root = nullptr; 79 | }; 80 | -------------------------------------------------------------------------------- /RangeQuery/MaxPrefixSegmentTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct PrefixSum { 5 | long long sum, prefix_sum; 6 | 7 | PrefixSum operator+(PrefixSum const& other) { 8 | return {sum + other.sum, 9 | std::max(prefix_sum, sum + other.prefix_sum)}; 10 | } 11 | }; 12 | 13 | class MaxPrefixSegmentTree { 14 | public: 15 | MaxPrefixSegmentTree(int count) { 16 | n = count; 17 | prefix_sums.assign(2 * n, {0, 0}); 18 | } 19 | 20 | void update(int idx, int add) { 21 | idx += n; 22 | int old_value = prefix_sums[idx].sum; 23 | int new_value = old_value + add; 24 | prefix_sums[idx] = {new_value, std::max(0, new_value)}; 25 | while (idx > 1) { 26 | idx /= 2; 27 | prefix_sums[idx] = prefix_sums[2 * idx] + prefix_sums[2 * idx + 1]; 28 | } 29 | } 30 | 31 | long long maximum(int left, int right) { // interval [left, right) 32 | left += n; 33 | right += n; 34 | 35 | std::vector from_left, from_right; 36 | while (left < right) { 37 | if (left & 1) 38 | from_left.push_back(prefix_sums[left++]); 39 | if (right & 1) 40 | from_right.push_back(prefix_sums[--right]); 41 | left >>= 1; 42 | right >>= 1; 43 | } 44 | 45 | while (!from_right.empty()) { 46 | from_left.push_back(from_right.back()); 47 | from_right.pop_back(); 48 | } 49 | long long best = 0; 50 | PrefixSum cur{0, 0}; 51 | for (auto const& ps : from_left) { 52 | cur = cur + ps; 53 | best = std::max(best, cur.prefix_sum); 54 | } 55 | return best; 56 | } 57 | 58 | private: 59 | int n; 60 | std::vector prefix_sums; 61 | }; 62 | -------------------------------------------------------------------------------- /RangeQuery/PersistentSegmentTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Node; 5 | 6 | std::deque cache; 7 | 8 | Node* fetch_new() { 9 | cache.emplace_back(); 10 | return &cache.back(); 11 | } 12 | 13 | Node* fetch_new(Node const& node) { 14 | cache.emplace_back(node); 15 | return &cache.back(); 16 | } 17 | 18 | struct Node { 19 | Node* left = nullptr; 20 | Node* right = nullptr; 21 | int data = std::numeric_limits::max(); 22 | 23 | void build(int l, int r) { 24 | if (l + 1 < r) { 25 | int m = (l + r) / 2; 26 | left = fetch_new(); 27 | right = fetch_new(); 28 | left->build(l, m); 29 | right->build(m, r); 30 | } 31 | } 32 | 33 | Node* set(int pos, int x, int l, int r) { 34 | Node* neww = fetch_new(*this); 35 | 36 | if (l + 1 == r) { 37 | neww->data = x; 38 | } else { 39 | int m = (l + r) / 2; 40 | if (pos < m) 41 | neww->left = neww->left->set(pos, x, l, m); 42 | else 43 | neww->right = neww->right->set(pos, x, m, r); 44 | neww->data = std::min(neww->left->data, neww->right->data); 45 | } 46 | return neww; 47 | } 48 | 49 | int min(int bl, int br, int l, int r) { 50 | if (bl >= r || br <= l) 51 | return std::numeric_limits::max(); 52 | 53 | if (bl <= l && r <= br) 54 | return data; 55 | 56 | int m = (l + r) / 2; 57 | return std::min(left->min(bl, br, l, m), right->min(bl, br, m, r)); 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | class SegmentTree { 7 | public: 8 | SegmentTree(int count) { 9 | n = count; 10 | data = std::vector(2 * n, 0); 11 | } 12 | 13 | SegmentTree(std::vector const &values) { 14 | n = values.size(); 15 | data = std::vector(2 * n); 16 | std::copy(values.begin(), values.end(), &data[0] + n); 17 | for (int idx = n - 1; idx > 0; idx--) 18 | data[idx] = std::min(data[idx * 2], data[idx * 2 + 1]); 19 | } 20 | 21 | void update(int idx, int value) { 22 | idx += n; 23 | data[idx] = value; 24 | 25 | while (idx > 1) { 26 | idx /= 2; 27 | data[idx] = std::min(data[2 * idx], data[2 * idx + 1]); 28 | } 29 | } 30 | 31 | int minimum(int left, int right) { // interval [left, right) 32 | int ret = std::numeric_limits::max(); 33 | left += n; 34 | right += n; 35 | 36 | while (left < right) { 37 | if (left & 1) ret = std::min(ret, data[left++]); 38 | if (right & 1) ret = std::min(ret, data[--right]); 39 | left >>= 1; 40 | right >>= 1; 41 | } 42 | return ret; 43 | } 44 | 45 | private: 46 | int n; 47 | std::vector data; 48 | }; 49 | 50 | int main() { 51 | SegmentTree st(5); 52 | st.update(0, 5); 53 | st.update(1, 2); 54 | st.update(2, 3); 55 | st.update(3, 1); 56 | st.update(4, 4); 57 | for (int i = 0; i < 5; i++) { 58 | std::cout << i << ": " << st.minimum(i, i+1) << std::endl; 59 | } 60 | 61 | std::cout << st.minimum(1, 4) << std::endl; 62 | st.update(3, 10); 63 | std::cout << st.minimum(1, 4) << std::endl; 64 | std::cout << st.minimum(0, 5) << std::endl; 65 | st.update(4, 0); 66 | std::cout << st.minimum(1, 4) << std::endl; 67 | std::cout << st.minimum(0, 5) << std::endl; 68 | 69 | SegmentTree st2({5, 2, 3, 1, 4}); 70 | } 71 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTree.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.List; 3 | import java.util.ArrayList; 4 | 5 | public class SegmentTree 6 | { 7 | private ArrayList data; 8 | private int n; 9 | 10 | public SegmentTree(List arr) { 11 | n = arr.size(); 12 | data = new ArrayList(2 * n); 13 | 14 | for (int idx = 0; idx < n; idx++) { 15 | data.add(0); 16 | } 17 | for (int idx = 0; idx < n; idx++) { 18 | data.add(arr.get(idx)); 19 | } 20 | for (int idx = n-1; idx > 0; idx--) { 21 | data.set(idx, Math.min(data.get(2*idx), data.get(2*idx+1))); 22 | } 23 | } 24 | 25 | public void update(int idx, int value) { 26 | idx += n; 27 | data.set(idx, value); 28 | 29 | while (idx > 1) { 30 | idx /= 2; 31 | data.set(idx, Math.min(data.get(2*idx), data.get(2*idx+1))); 32 | } 33 | } 34 | 35 | public int minimum(int left, int right) { 36 | left += n; 37 | right += n; 38 | int min = Integer.MAX_VALUE; 39 | 40 | while (left < right) { 41 | if ((left & 1) == 1) { 42 | min = Math.min(min, data.get(left)); 43 | left++; 44 | } 45 | if ((right & 1) == 1) { 46 | right--; 47 | min = Math.min(min, data.get(right)); 48 | } 49 | left >>= 1; 50 | right >>= 1; 51 | } 52 | 53 | return min; 54 | } 55 | 56 | public static void main(String[] args) { 57 | SegmentTree st = new SegmentTree(Arrays.asList(5, 2, 3, 1, 4)); 58 | for (int i = 0; i < 5; i++) { 59 | System.out.println(st.minimum(i, i+1)); 60 | } 61 | System.out.println(st.minimum(i, i+1)); 62 | 63 | System.out.println(st.minimum(1, 4)); 64 | st.update(3, 10); 65 | System.out.println(st.minimum(1, 4)); 66 | System.out.println(st.minimum(0, 5)); 67 | st.update(4, 0); 68 | System.out.println(st.minimum(1, 4)); 69 | System.out.println(st.minimum(0, 5)); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTree.py: -------------------------------------------------------------------------------- 1 | class SegmentTree: 2 | def __init__(self, values): 3 | self.data = [0 for _ in values] + values 4 | self.n = len(values) 5 | 6 | for idx in reversed(range(1, self.n)): 7 | self.data[idx] = min(self.data[2*idx], self.data[2*idx+1]) 8 | 9 | def update(self, idx, value): 10 | idx += self.n 11 | self.data[idx] = value 12 | 13 | while idx > 1: 14 | idx //= 2 15 | self.data[idx] = min(self.data[2*idx], self.data[2*idx+1]) 16 | 17 | def minimum(self, left, right): 18 | left += self.n 19 | right += self.n 20 | minimum = self.data[left] 21 | 22 | while left < right: 23 | if left % 2: 24 | minimum = min(minimum, self.data[left]) 25 | left += 1 26 | if right % 2: 27 | right -= 1 28 | minimum = min(minimum, self.data[right]) 29 | left //= 2 30 | right //= 2 31 | 32 | return minimum 33 | 34 | 35 | if __name__ == '__main__': 36 | st = SegmentTree([1, 5, 3, 7, 5]) 37 | print(st.minimum(0, 3)) 38 | print(st.minimum(1, 3)) 39 | print(st.minimum(1, 2)) 40 | 41 | st.update(0,3) 42 | st.update(2,4) 43 | 44 | print() 45 | print(st.minimum(0, 3)) 46 | print(st.minimum(1, 3)) 47 | print(st.minimum(1, 2)) 48 | 49 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTreeAbstract.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | template 6 | class SegmentTree { 7 | public: 8 | using CombineFkt = std::function; 9 | 10 | SegmentTree(int count, CombineFkt combine) : combine{combine} { 11 | n = count; 12 | data.resize(2 * n); 13 | } 14 | 15 | SegmentTree(std::vector const &values, CombineFkt combine) : combine{combine} { 16 | n = values.size(); 17 | data.resize(2 * n); 18 | std::copy(values.begin(), values.end(), &data[n]); 19 | for (int idx = n - 1; idx > 0; idx--) 20 | data[idx] = combine(data[idx * 2], data[idx * 2 + 1]); 21 | } 22 | 23 | void update(int idx, Segment value) { 24 | idx += n; 25 | data[idx] = value; 26 | 27 | while (idx > 1) { 28 | idx /= 2; 29 | data[idx] = combine(data[2 * idx], data[2 * idx + 1]); 30 | } 31 | } 32 | 33 | Segment minimum(int left, int right) { // interval [left, right) 34 | left += n; 35 | right += n; 36 | 37 | if (left + 1 == right) 38 | return data[left]; 39 | 40 | Segment ret_l = data[left++], ret_r = data[--right]; 41 | 42 | while (left < right) { 43 | if (left & 1) ret_l = combine(ret_l, data[left++]); 44 | if (right & 1) ret_r = combine(data[--right], ret_r); 45 | left >>= 1; 46 | right >>= 1; 47 | } 48 | return combine(ret_l, ret_r); 49 | } 50 | 51 | private: 52 | int n; 53 | std::vector data; 54 | CombineFkt combine; 55 | }; 56 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTreeDynamic.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Node 4 | { 5 | int data = 0; 6 | Node* L = nullptr; 7 | Node* R = nullptr; 8 | int todo = 0; 9 | }; 10 | 11 | class SegmentTreeRec 12 | { 13 | public: 14 | SegmentTreeRec(int n) : n(n) { 15 | nodes.reserve(15000010); 16 | auto start = createNode(); 17 | start->data = n; 18 | start->todo = 2; 19 | } 20 | 21 | Node* createNode() { 22 | nodes.emplace_back(); 23 | return &nodes[nodeCnt++]; 24 | } 25 | 26 | void update(int l, int r, int val, Node* cur=nullptr, int seg_l=0, int seg_r=-1) { 27 | if (seg_r == -1) 28 | seg_r = n; 29 | 30 | if (seg_r <= l || seg_l >= r) 31 | return; 32 | 33 | if (l <= seg_l && r >= seg_r) { 34 | cur->data = val; 35 | cur->todo = val; 36 | return; 37 | } 38 | 39 | if (cur->L == nullptr) 40 | cur->L = createNode(); 41 | if (cur->R == nullptr) 42 | cur->R = createNode(); 43 | 44 | int seg_m = seg_l + (seg_r - seg_l) / 2; 45 | if (cur->todo == 1) { 46 | cur->L->data = 0; 47 | cur->L->todo = 1; 48 | cur->R->data = 0; 49 | cur->R->todo = 1; 50 | cur->todo = 0; 51 | } 52 | if (cur->todo == 2) { 53 | cur->L->data = seg_m - seg_l; 54 | cur->L->todo = 2; 55 | cur->R->data = seg_r - seg_m; 56 | cur->R->todo = 2; 57 | cur->todo = 0; 58 | } 59 | 60 | update(l, r, val, cur->L, seg_l, seg_m); 61 | update(l, r, val, cur->R, seg_m, seg_r); 62 | cur->data = cur->L->data + cur->R->data; 63 | } 64 | 65 | int n; 66 | std::vector nodes; 67 | Node* start; 68 | int nodeCnt = 0; 69 | }; 70 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTreeMin.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class SegmentTree { 5 | public: 6 | SegmentTree(int count) { 7 | n = count; 8 | data.assign(2 * n, 0); 9 | } 10 | 11 | SegmentTree(std::vector const &values) { 12 | n = values.size(); 13 | data.resize(2 * n); 14 | std::copy(values.begin(), values.end(), &data[0] + n); 15 | for (int idx = n - 1; idx > 0; idx--) 16 | data[idx] = std::min(data[idx * 2], data[idx * 2 + 1]); 17 | } 18 | 19 | void update(int idx, int value) { 20 | idx += n; 21 | data[idx] = value; 22 | 23 | while (idx > 1) { 24 | idx /= 2; 25 | data[idx] = std::min(data[2 * idx], data[2 * idx + 1]); 26 | } 27 | } 28 | 29 | int minimum(int left, int right) { // interval [left, right) 30 | int ret = std::numeric_limits::max(); 31 | left += n; 32 | right += n; 33 | 34 | while (left < right) { 35 | if (left & 1) ret = std::min(ret, data[left++]); 36 | if (right & 1) ret = std::min(ret, data[--right]); 37 | left >>= 1; 38 | right >>= 1; 39 | } 40 | return ret; 41 | } 42 | 43 | private: 44 | int n; 45 | std::vector data; 46 | }; 47 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTreeRec.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class SegmentTreeRec 5 | { 6 | public: 7 | SegmentTreeRec(int n) : n(n) { data.assign(4 * n, 0); } 8 | 9 | SegmentTreeRec(std::vector const &values) 10 | { 11 | n = values.size(); 12 | data.assign(4 * n, 0); 13 | build(values); 14 | } 15 | 16 | void build(std::vector const &values, int id = 1, int l = 0, int r = -1) { 17 | if (r == -1) 18 | r = n; 19 | 20 | if (l + 1 == r) { 21 | data[id] = values[l]; 22 | } else { 23 | int m = (l + r) >> 1; 24 | build(values, id << 1, l, m); 25 | build(values, id << 1 | 1, m, r); 26 | data[id] = std::min(data[id << 1], data[id << 1 | 1]); 27 | } 28 | } 29 | 30 | int minimum(int x, int y, int id = 1, int l = 0, int r = -1) 31 | { 32 | if (r == -1) 33 | r = n; 34 | 35 | if (x >= r || y <= l) { 36 | return std::numeric_limits::max(); 37 | } else if (x <= l && r <= y) { 38 | return data[id]; 39 | } else { 40 | int m = (l + r) >> 1; 41 | return std::min(minimum(x, y, id << 1, l, m), 42 | minimum(x, y, id << 1 | 1, m, r)); 43 | } 44 | } 45 | 46 | void update(int pos, int addend, int id = 1, int l = 0, int r = -1) 47 | { 48 | if (r == -1) 49 | r = n; 50 | 51 | if (pos < l || pos >= r) { 52 | } else if (l == pos && pos + 1 == r) { 53 | data[id] += addend; 54 | } else { 55 | int m = (l + r) >> 1; 56 | update(pos, addend, id << 1, l, m); 57 | update(pos, addend, id << 1 | 1, m, r); 58 | data[id] = std::min(data[id << 1], data[id << 1 | 1]); 59 | } 60 | } 61 | 62 | private: 63 | int n; 64 | std::vector data; 65 | }; 66 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTreeRecLazyLinearFunktion.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct LinearFunktion 4 | { 5 | long long k = 1, d = 0; 6 | void compose(LinearFunktion f) { 7 | k *= f.k; 8 | d = f.k * d + f.d; 9 | } 10 | }; 11 | 12 | class SegmentTreeRecLazy 13 | { 14 | public: 15 | SegmentTreeRecLazy(int n) : n(n) 16 | { 17 | data.assign(4 * n, 0); 18 | todo.resize(4 * n); 19 | } 20 | 21 | long long sum(int x, int y, int id = 1, int l = 0, int r = -1) 22 | { 23 | if (r == -1) 24 | r = n; 25 | 26 | if (x >= r || y <= l) { 27 | return 0; 28 | } else if (x <= l && r <= y) { 29 | return data[id]; 30 | } else { 31 | push(id, l, r); 32 | int m = (l + r) >> 1; 33 | return sum(x, y, id << 1, l, m) + sum(x, y, id << 1 | 1, m, r); 34 | } 35 | } 36 | 37 | void apply(int x, int y, LinearFunktion f, int id = 1, int l = 0, int r = -1) 38 | { 39 | if (r == -1) 40 | r = n; 41 | 42 | if (x >= r || y <= l) { 43 | } else if (x <= l && r <= y) { 44 | data[id] = data[id] * f.k + f.d * (r - l); 45 | todo[id].compose(f); 46 | } else { 47 | push(id, l, r); 48 | int m = (l + r) >> 1; 49 | apply(x, y, f, id << 1, l, m); 50 | apply(x, y, f, id << 1 | 1, m, r); 51 | data[id] = data[id << 1] + data[id << 1 | 1]; 52 | } 53 | } 54 | 55 | private: 56 | void push(int id, int l, int r) 57 | { 58 | int m = (l + r) >> 1; 59 | 60 | data[id << 1] *= todo[id].k; 61 | data[id << 1] += todo[id].d * (m - l); 62 | todo[id << 1].compose(todo[id]); 63 | 64 | data[id << 1 | 1] *= todo[id].k; 65 | data[id << 1 | 1] += todo[id].d * (r - m); 66 | todo[id << 1 | 1].compose(todo[id]); 67 | 68 | todo[id] = {1, 0}; 69 | } 70 | 71 | int n; 72 | std::vector data; 73 | std::vector todo; 74 | }; 75 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTreeRecLazyMin.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class SegmentTreeRecLazy 5 | { 6 | public: 7 | SegmentTreeRecLazy(int n) : n(n) 8 | { 9 | data.assign(4 * n, 0); 10 | todo.assign(4 * n, 0); 11 | } 12 | 13 | SegmentTreeRecLazy(std::vector const& v) { 14 | n = v.size(); 15 | data.assign(4 * n, 0); 16 | todo.assign(4 * n, 0); 17 | build(v); 18 | } 19 | 20 | void build(std::vector const& v, int id = 1, int l = 0, int r = -1) { 21 | if (r == -1) 22 | r = n; 23 | 24 | if (l == r - 1) { 25 | data[id] = v[l]; 26 | } else { 27 | int m = (l + r) >> 1; 28 | build(v, id << 1, l, m); 29 | build(v, id << 1 | 1, m, r); 30 | data[id] = std::min(data[id << 1], data[id << 1 | 1]); 31 | } 32 | } 33 | 34 | int minimum(int x, int y, int id = 1, int l = 0, int r = -1) 35 | { 36 | if (r == -1) 37 | r = n; 38 | 39 | if (x >= r || y <= l) { 40 | return std::numeric_limits::max(); 41 | } else if (x <= l && r <= y) { 42 | return data[id]; 43 | } else { 44 | push(id, l, r); 45 | int m = (l + r) >> 1; 46 | return std::min(minimum(x, y, id << 1, l, m), 47 | minimum(x, y, id << 1 | 1, m, r)); 48 | } 49 | } 50 | 51 | void update(int x, int y, int addend, int id = 1, int l = 0, int r = -1) 52 | { 53 | if (r == -1) 54 | r = n; 55 | 56 | if (x >= r || y <= l) { 57 | } else if (x <= l && r <= y) { 58 | data[id] += addend; 59 | todo[id] += addend; 60 | } else { 61 | push(id, l, r); 62 | int m = (l + r) >> 1; 63 | update(x, y, addend, id << 1, l, m); 64 | update(x, y, addend, id << 1 | 1, m, r); 65 | data[id] = std::min(data[id << 1], data[id << 1 | 1]); 66 | } 67 | } 68 | 69 | private: 70 | void push(int id, int l, int r) 71 | { 72 | data[id << 1] += todo[id]; 73 | todo[id << 1] += todo[id]; 74 | data[id << 1 | 1] += todo[id]; 75 | todo[id << 1 | 1] += todo[id]; 76 | todo[id] = 0; 77 | } 78 | 79 | int n; 80 | std::vector data, todo; 81 | }; 82 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTreeRecLazySum.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class SegmentTreeRecLazy 5 | { 6 | public: 7 | SegmentTreeRecLazy(int n) : n(n) 8 | { 9 | data.assign(4 * n, 0); 10 | todo.assign(4 * n, 0); 11 | } 12 | 13 | SegmentTreeRecLazy(std::vector const& v) { 14 | n = v.size(); 15 | data.assign(4 * n, 0); 16 | todo.assign(4 * n, 0); 17 | build(v); 18 | } 19 | 20 | void build(std::vector const& v, int id = 1, int l = 0, int r = -1) { 21 | if (r == -1) 22 | r = n; 23 | 24 | if (l == r - 1) { 25 | data[id] = v[l]; 26 | } else { 27 | int m = (l + r) >> 1; 28 | build(v, id << 1, l, m); 29 | build(v, id << 1 | 1, m, r); 30 | data[id] = data[id << 1] + data[id << 1 | 1]; 31 | } 32 | } 33 | 34 | long long sum(int x, int y, int id = 1, int l = 0, int r = -1) 35 | { 36 | if (r == -1) 37 | r = n; 38 | 39 | if (x >= r || y <= l) { 40 | return 0; 41 | } else if (x <= l && r <= y) { 42 | return data[id]; 43 | } else { 44 | push(id, l, r); 45 | int m = (l + r) >> 1; 46 | return sum(x, y, id << 1, l, m) + sum(x, y, id << 1 | 1, m, r); 47 | } 48 | } 49 | 50 | void add(int x, int y, long long addend, int id = 1, int l = 0, int r = -1) 51 | { 52 | if (r == -1) 53 | r = n; 54 | 55 | if (x >= r || y <= l) { 56 | } else if (x <= l && r <= y) { 57 | data[id] += addend * (r - l); 58 | todo[id] += addend; 59 | } else { 60 | push(id, l, r); 61 | int m = (l + r) >> 1; 62 | add(x, y, addend, id << 1, l, m); 63 | add(x, y, addend, id << 1 | 1, m, r); 64 | data[id] = data[id << 1] + data[id << 1 | 1]; 65 | } 66 | } 67 | 68 | private: 69 | void push(int id, int l, int r) 70 | { 71 | int m = (l + r) >> 1; 72 | data[id << 1] += todo[id] * (m - l); 73 | todo[id << 1] += todo[id]; 74 | data[id << 1 | 1] += todo[id] * (r - m); 75 | todo[id << 1 | 1] += todo[id]; 76 | todo[id] = 0; 77 | } 78 | 79 | int n; 80 | std::vector data, todo; 81 | }; 82 | -------------------------------------------------------------------------------- /RangeQuery/SegmentTreeSum.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class SegmentTree { 5 | public: 6 | SegmentTree(int count) { 7 | n = count; 8 | data.assign(2 * n, 0); 9 | } 10 | 11 | SegmentTree(std::vector const &values) { 12 | n = values.size(); 13 | data.resize(2 * n); 14 | std::copy(values.begin(), values.end(), &data[0] + n); 15 | for (int idx = n - 1; idx > 0; idx--) 16 | data[idx] = data[2 * idx] + data[2 * idx + 1]; 17 | } 18 | 19 | void update(int idx, int value) { 20 | idx += n; 21 | data[idx] = value; 22 | 23 | while (idx > 1) { 24 | idx /= 2; 25 | data[idx] = data[2 * idx] + data[2 * idx + 1]; 26 | } 27 | } 28 | 29 | int sum(int left, int right) { // interval [left, right) 30 | int ret = 0; 31 | left += n; 32 | right += n; 33 | 34 | while (left < right) { 35 | if (left & 1) ret += data[left++]; 36 | if (right & 1) ret += data[--right]; 37 | left >>= 1; 38 | right >>= 1; 39 | } 40 | return ret; 41 | } 42 | 43 | private: 44 | int n; 45 | std::vector data; 46 | }; 47 | -------------------------------------------------------------------------------- /RangeQuery/SparseTable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | vector v = {5, 2, 4, 7, 6, 3, 1, 2}; 8 | 9 | vector log_table(v.size() + 1, 0); 10 | for (int i = 2; i < log_table.size(); i++) 11 | log_table[i] = log_table[i/2] + 1; 12 | 13 | vector> sparse_table(log_table.back() + 1, vector(v.size())); 14 | sparse_table[0] = v; 15 | for (int row = 1; row < sparse_table.size(); row++) { 16 | for (int i = 0; i + (1 << row) <= v.size(); i++) { 17 | sparse_table[row][i] = min(sparse_table[row-1][i], sparse_table[row-1][i+(1<<(row-1))]); 18 | } 19 | } 20 | 21 | while (1) { 22 | int l, r; 23 | cin >> l >> r; 24 | // minimum of interval of indices [l, r) 25 | // minimum of v[l], v[l+1], ... v[r-1] 26 | int log = log_table[r - l]; 27 | int minimum = min(sparse_table[log][l], sparse_table[log][r - (1 << log)]); 28 | cout << minimum << endl; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /RangeQuery/SparseTable.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class SparseTable 4 | { 5 | public: 6 | SparseTable(std::vector v) 7 | { 8 | log_table.assign(v.size() + 1, 0); 9 | for (auto i = 2UL; i < log_table.size(); i++) 10 | log_table[i] = log_table[i / 2] + 1; 11 | 12 | sparse_table.assign(log_table.back() + 1, std::vector(v.size())); 13 | sparse_table[0] = v; 14 | for (auto row = 1UL; row < sparse_table.size(); row++) { 15 | for (auto i = 0UL; i + (1 << row) <= v.size(); i++) { 16 | sparse_table[row][i] = 17 | std::min(sparse_table[row - 1][i], 18 | sparse_table[row - 1][i + (1 << (row - 1))]); 19 | } 20 | } 21 | } 22 | 23 | int minimum(int l, int r) 24 | { 25 | int log = log_table[r - l]; 26 | return std::min(sparse_table[log][l], 27 | sparse_table[log][r - (1 << log)]); 28 | } 29 | 30 | private: 31 | std::vector log_table; 32 | std::vector> sparse_table; 33 | }; 34 | -------------------------------------------------------------------------------- /RangeQuery/WaveletTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "WaveletTree.h" 3 | using namespace std; 4 | 5 | 6 | int main() { 7 | ios_base::sync_with_stdio(false); 8 | cin.tie(NULL); 9 | 10 | int n, m; 11 | cin >> n >> m; 12 | vector v(n); 13 | for (int i = 0; i < n; i++) { 14 | cin >> v[i]; 15 | } 16 | 17 | set s(v.begin(), v.end()); 18 | vector w(s.begin(), s.end()); 19 | for (auto &e : v) { 20 | e = lower_bound(w.begin(), w.end(), e) - w.begin(); 21 | } 22 | 23 | WaveletTree wt(v, w.size()); 24 | while (m --> 0) { 25 | int l, r, k; 26 | cin >> l >> r >> k; 27 | int x = wt.kTh(l-1, r, k); 28 | cout << w[x] << endl; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /RangeQuery/WaveletTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class WaveletTree 5 | { 6 | public: 7 | WaveletTree(std::vector &v, int size) : s(size), nodes(2 * size) 8 | { 9 | build(v.begin(), v.end(), 0, s - 1, 1); 10 | } 11 | 12 | // l, r is 0 based 13 | // k is 1 based 14 | // range [l, r) 15 | int kTh(int l, int r, int k) 16 | { 17 | int idx = 1; 18 | int L = 0, U = s - 1; 19 | while (L != U) { 20 | int M = (L + U) / 2; 21 | int ll = nodes[idx][l]; 22 | int lr = nodes[idx][r]; 23 | if (k <= lr - ll) { 24 | l = ll, r = lr, U = M, idx = 2 * idx; 25 | } else { 26 | k -= lr - ll, l -= ll, r -= lr, L = M + 1, idx = 2 * idx + 1; 27 | } 28 | } 29 | return L; 30 | } 31 | 32 | private: 33 | int s; 34 | std::vector> nodes; 35 | 36 | using iter = std::vector::iterator; 37 | 38 | void build(iter b, iter e, int L, int U, int idx) 39 | { 40 | if (L == U) 41 | return; 42 | int M = (L + U) / 2; 43 | 44 | nodes[idx].resize(distance(b, e) + 1); 45 | nodes[idx][0] = 0; 46 | int i = 0; 47 | for (iter it = b; it != e; ++it) { 48 | nodes[idx][i + 1] = nodes[idx][i] + (*it <= M); 49 | i++; 50 | } 51 | 52 | iter p = std::stable_partition(b, e, [M](int i) { return i <= M; }); 53 | 54 | build(b, p, L, M, idx * 2); 55 | build(p, e, M + 1, U, idx * 2 + 1); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /Strings/AhoCorasick.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | constexpr int K = 26; 7 | struct Vertex { 8 | std::array next; 9 | bool terminal = false; 10 | int terminal_idx = -1; 11 | int p = -1; 12 | char pch; 13 | int depth = 0; 14 | int link = 0; 15 | int next_terminal = 0; 16 | std::array go; 17 | 18 | Vertex(int p, char ch, int depth) : p(p), pch(ch), depth(depth) { 19 | std::fill(next.begin(), next.end(), 0); 20 | std::fill(go.begin(), go.end(), 0); 21 | } 22 | }; 23 | 24 | class AhoCorasick { 25 | public: 26 | AhoCorasick() : t(1, {-1, '$', 0}) {} 27 | 28 | void add_string(std::string const& s, int idx) { 29 | int v = 0; 30 | for (char ch : s) { 31 | int c = ch - 'a'; 32 | if (!t[v].next[c]) { 33 | t[v].next[c] = t.size(); 34 | t.emplace_back(v, ch, t[v].depth + 1); 35 | } 36 | v = t[v].next[c]; 37 | } 38 | t[v].terminal = true; 39 | t[v].terminal_idx = idx; 40 | } 41 | 42 | void push_links() { 43 | std::queue q; 44 | q.push(0); 45 | while (!q.empty()) { 46 | int v = q.front(); 47 | auto& cur = t[v]; 48 | auto& link = t[cur.link]; 49 | q.pop(); 50 | cur.next_terminal = link.terminal ? cur.link : link.next_terminal; 51 | 52 | for (int c = 0; c < K; c++) { 53 | if (cur.next[c]) { 54 | t[cur.next[c]].link = v ? link.next[c] : 0; 55 | q.push(cur.next[c]); 56 | } else { 57 | cur.next[c] = link.next[c]; 58 | } 59 | } 60 | } 61 | } 62 | 63 | int transition(int idx, char c) { 64 | return t[idx].next[c - 'a']; 65 | } 66 | 67 | Vertex const& getInfo(int idx) { 68 | return t[idx]; 69 | } 70 | 71 | private: 72 | std::vector t; 73 | }; 74 | -------------------------------------------------------------------------------- /Strings/DeBruijn.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class DeBruijn { 4 | std::string sequence; 5 | std::string a; 6 | int k, n; 7 | public: 8 | // de Bruijn sequence for alphabet k 9 | // and subsequences of length n. 10 | DeBruijn(int k, int n) : k(k), n(n) {} 11 | 12 | // returns a cyclic string 13 | std::string operator()() { 14 | a.assign(k * n, 'a'); 15 | sequence = ""; 16 | sequence.reserve(power(k, n)); 17 | 18 | db(1, 1); 19 | return sequence; 20 | } 21 | 22 | private: 23 | void db(int t, int p) { 24 | if (t > n) { 25 | if (n % p == 0) 26 | sequence += a.substr(1, p); 27 | } else { 28 | a[t] = a[t - p]; 29 | db(t + 1, p); 30 | for (char c = a[t - p] + 1; c < 'a' + k; c++) { 31 | a[t] = c; 32 | db(t + 1, t); 33 | } 34 | } 35 | } 36 | 37 | int power(int x, int e) { 38 | return e ? x * power(x, e-1) : 1; 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /Strings/Hashing.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Hashing 5 | { 6 | public: 7 | Hashing(std::string const& s, int p = 31, int mod = 1'000'000'007) 8 | : mod(mod) 9 | { 10 | psum.push_back(0); 11 | long long power = 1; 12 | long long inv = inverse(p, mod); 13 | inv_powers.push_back(1); 14 | for (char c : s) { 15 | psum.push_back((psum.back() + power * (c - 'a' + 1)) % mod); 16 | power = power * p % mod;; 17 | inv_powers.push_back(inv_powers.back() * inv % mod); 18 | } 19 | } 20 | 21 | int hash(int i, int j) { 22 | long long h = psum[j+1] - psum[i]; 23 | if (h < 0) 24 | h += mod; 25 | return h * inv_powers[i] % mod; 26 | } 27 | 28 | private: 29 | long long inverse(long long base, int M) { 30 | int e = M - 2; 31 | long long result = 1; 32 | base %= M; 33 | while (e) { 34 | if (e & 1) 35 | result = (result * base) % M; 36 | base = (base * base) % M; 37 | e >>= 1; 38 | } 39 | return result; 40 | } 41 | 42 | std::vector psum; 43 | std::vector inv_powers; 44 | int mod; 45 | }; 46 | -------------------------------------------------------------------------------- /Strings/HashingMult.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | class Hashing { 6 | public: 7 | Hashing(std::string const& s, std::array, C> pm) { 8 | n = s.size(); 9 | for (int c = 0; c < C; c++) { 10 | int p = pm[c].first; 11 | m[c] = pm[c].second; 12 | p_pow[c].assign(n, 0); 13 | p_pow[c][0] = 1; 14 | for (int i = 1; i < n; i++) { 15 | p_pow[c][i] = (p_pow[c][i - 1] * p) % m[c]; 16 | } 17 | 18 | h[c].assign(n + 1, 0); 19 | for (int i = 0; i < n; i++) { 20 | h[c][i + 1] = (h[c][i] + (s[i] - 'a' + 1) * p_pow[c][i]) % m[c]; 21 | } 22 | } 23 | } 24 | 25 | std::array hash(int i, int l) const { 26 | std::array hashes; 27 | for (int c = 0; c < C; c++) { 28 | long long cur_h = (h[c][i + l] + m[c] - h[c][i]) % m[c]; 29 | hashes[c] = cur_h * p_pow[c][n - i - 1] % m[c]; 30 | } 31 | return hashes; 32 | } 33 | 34 | std::array default_values() const { 35 | std::array arr; 36 | std::fill(arr.begin(), arr.end(), -1); 37 | return arr; 38 | } 39 | 40 | int n; 41 | std::array, C> p_pow; 42 | std::array, C> h; 43 | std::array m; 44 | }; 45 | 46 | std::array, 3> pm3 = {{{31, 1'000'000'007}, {37, 1'000'000'007}, {41, 900'000'011}}}; 47 | -------------------------------------------------------------------------------- /Strings/PrefixAutomaton.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class PrefixAutomaton { 5 | public: 6 | PrefixAutomaton(std::string str) : s(str) { 7 | s += '#'; 8 | int n = s.size(); 9 | pi = prefix_function(s); 10 | aut.assign(n, std::vector(26)); 11 | for (int i = 0; i < n; i++) { 12 | for (int c = 0; c < 26; c++) { 13 | if (i > 0 && 'a' + c != s[i]) 14 | aut[i][c] = aut[pi[i-1]][c]; 15 | else 16 | aut[i][c] = i + ('a' + c == s[i]); 17 | } 18 | } 19 | } 20 | 21 | int transition(int state, char c) { 22 | return aut[state][c - 'a']; 23 | } 24 | 25 | static std::vector prefix_function(std::string s) { 26 | int n = (int)s.length(); 27 | std::vector pi(n); 28 | for (int i = 1; i < n; i++) { 29 | int j = pi[i-1]; 30 | while (j > 0 && s[i] != s[j]) 31 | j = pi[j-1]; 32 | if (s[i] == s[j]) 33 | j++; 34 | pi[i] = j; 35 | } 36 | return pi; 37 | } 38 | 39 | private: 40 | std::string s; 41 | std::vector pi; 42 | std::vector> aut; 43 | }; 44 | -------------------------------------------------------------------------------- /Strings/SuffixArray.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct Suffix { 7 | using Ranks = std::array; 8 | // rank and next rank 9 | 10 | int idx; 11 | Ranks ranks; 12 | 13 | bool operator<(Suffix const& b) { return ranks < b.ranks; } 14 | }; 15 | 16 | class SuffixArray 17 | { 18 | public: 19 | SuffixArray(std::string const& s) 20 | { 21 | buildSuffixArray(s); 22 | kasai(s); 23 | } 24 | 25 | std::vector suffixArray; 26 | std::vector lcp; 27 | 28 | private: 29 | void buildSuffixArray(std::string const& s) 30 | { 31 | // O(n logn logn) 32 | int n = s.size(); 33 | std::vector suffixes(n); 34 | for (int i = 0; i < n; i++) { 35 | suffixes[i] = {i, {{s[i] - '0', i == n - 1 ? -1 : s[i + 1] - '0'}}}; 36 | } 37 | sort(suffixes.begin(), suffixes.end()); 38 | 39 | std::vector indices(n); 40 | for (int k = 2; k <= n; k *= 2) { 41 | int rank = 0; 42 | Suffix::Ranks prev_ranks = {{-1, -1}}; 43 | for (int i = 0; i < n; i++) { 44 | if (i && prev_ranks < suffixes[i].ranks) { 45 | rank++; 46 | } 47 | prev_ranks = suffixes[i].ranks; 48 | suffixes[i].ranks[0] = rank; 49 | indices[suffixes[i].idx] = i; 50 | } 51 | 52 | for (int i = 0; i < n; i++) { 53 | int next_idx = suffixes[i].idx + k; 54 | suffixes[i].ranks[1] = 55 | next_idx < n ? suffixes[indices[next_idx]].ranks[0] : -1; 56 | } 57 | 58 | sort(suffixes.begin(), suffixes.end()); 59 | } 60 | 61 | suffixArray.resize(n); 62 | for (int i = 0; i < n; i++) { 63 | suffixArray[i] = suffixes[i].idx; 64 | } 65 | } 66 | 67 | void kasai(std::string const& s) 68 | { 69 | int n = s.size(); 70 | lcp.resize(n); 71 | 72 | std::vector inverse(n); 73 | for (int i = 0; i < n; i++) { 74 | inverse[suffixArray[i]] = i; 75 | } 76 | 77 | int k = 0; 78 | for (int i = 0; i < n; i++) { 79 | if (inverse[i] == n - 1) { 80 | k = 0; 81 | } else { 82 | int j = suffixArray[inverse[i] + 1]; 83 | while (i + k < n && j + k < n && s[i + k] == s[j + k]) { 84 | k++; 85 | } 86 | } 87 | lcp[inverse[i]] = k; 88 | if (k > 0) { 89 | k--; 90 | } 91 | } 92 | } 93 | }; 94 | -------------------------------------------------------------------------------- /Trie/BinaryTrie.h: -------------------------------------------------------------------------------- 1 | struct BinaryTrie { 2 | BinaryTrie() { 3 | ch[0] = ch[1] = nullptr; 4 | count = 0; 5 | } 6 | 7 | void add(int val, int idx=30) { 8 | count++; 9 | if (idx >= 0) { 10 | int c = (val & (1 << idx)) ? 1 : 0; 11 | if (!ch[c]) 12 | ch[c] = new BinaryTrie(); 13 | ch[c]->add(val, idx - 1); 14 | } 15 | } 16 | 17 | bool remove(int val, int idx=30) { 18 | if (idx >= 0) { 19 | int c = (val & (1 << idx)) ? 1 : 0; 20 | bool removed = ch[c] && ch[c]->remove(val, idx - 1); 21 | count -= removed; 22 | return removed; 23 | } else { 24 | if (count) { 25 | count--; 26 | return true; 27 | } else { 28 | return false; 29 | } 30 | } 31 | } 32 | 33 | int countSmaller(int val, int idx=30) { 34 | int cnt = 0; 35 | if (idx >= 0) { 36 | int c = (val & (1 << idx)) ? 1 : 0; 37 | if (c == 1 && ch[0]) 38 | cnt += ch[0]->count; 39 | if (ch[c]) 40 | cnt += ch[c]->countSmaller(val, idx-1); 41 | } 42 | return cnt; 43 | } 44 | 45 | int count; 46 | BinaryTrie* ch[2]; 47 | }; 48 | -------------------------------------------------------------------------------- /Trie/PersistentBinaryCountTrie.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct BinaryCountTrie; 4 | 5 | std::deque cache; 6 | 7 | BinaryCountTrie* fetch_new() { 8 | cache.emplace_back(); 9 | return &cache.back(); 10 | } 11 | 12 | BinaryCountTrie* fetch_new(BinaryCountTrie const& node) { 13 | cache.emplace_back(node); 14 | return &cache.back(); 15 | } 16 | 17 | struct BinaryCountTrie { 18 | BinaryCountTrie() { 19 | for (int i = 0; i < 2; i++) { 20 | ch[i] = nullptr; 21 | } 22 | count = 0; 23 | } 24 | 25 | BinaryCountTrie(BinaryCountTrie* old) { 26 | for (int i = 0; i < 2; i++) { 27 | ch[i] = old->ch[i]; 28 | } 29 | count = old->count; 30 | } 31 | 32 | BinaryCountTrie* add(int val, int idx=30) { 33 | auto neww = fetch_new(*this); 34 | neww->count++; 35 | if (idx >= 0) { 36 | int c = (val & (1 << idx)) ? 1 : 0; 37 | if (!neww->ch[c]) 38 | neww->ch[c] = fetch_new(); 39 | neww->ch[c] = neww->ch[c]->add(val, idx - 1); 40 | } 41 | return neww; 42 | } 43 | 44 | BinaryCountTrie* remove(int val, int idx=30) { 45 | auto neww = fetch_new(*this); 46 | neww->count--; 47 | if (idx >= 0) { 48 | int c = (val & (1 << idx)) ? 1 : 0; 49 | if (neww->ch[c]) 50 | neww->ch[c] = neww->ch[c]->remove(val, idx - 1); 51 | } 52 | return neww; 53 | } 54 | 55 | int countSmaller(int val, int idx=30) { 56 | int cnt = 0; 57 | if (idx >= 0) { 58 | int c = (val & (1 << idx)) ? 1 : 0; 59 | for (int i = 0; i < c; i++) { 60 | if (ch[i]) 61 | cnt += ch[i]->count; 62 | } 63 | if (ch[c]) 64 | cnt += ch[c]->countSmaller(val, idx-1); 65 | } 66 | return cnt; 67 | } 68 | 69 | int count; 70 | BinaryCountTrie* ch[2]; 71 | }; 72 | -------------------------------------------------------------------------------- /Trie/PersistentStringTrie.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct StringTrieNode; 5 | 6 | std::deque cache; 7 | 8 | StringTrieNode* fetch_new() { 9 | cache.emplace_back(); 10 | return &cache.back(); 11 | } 12 | 13 | StringTrieNode* fetch_new(StringTrieNode const& node) { 14 | cache.emplace_back(node); 15 | return &cache.back(); 16 | } 17 | 18 | struct StringTrieNode { 19 | StringTrieNode() { 20 | for (int i = 0; i < 26; i++) { 21 | ch[i] = nullptr; 22 | } 23 | data = -1; 24 | } 25 | 26 | StringTrieNode(StringTrieNode* old) { 27 | for (int i = 0; i < 26; i++) { 28 | ch[i] = old->ch[i]; 29 | } 30 | data = old->data; 31 | } 32 | 33 | StringTrieNode* add(std::string const& s, int priority, int idx=0) { 34 | auto neww = fetch_new(*this); 35 | if (idx == (int)s.size()) { 36 | neww->data = priority; 37 | } else { 38 | int c = s[idx] - 'a'; 39 | if (!ch[c]) 40 | neww->ch[c] = fetch_new(); 41 | neww->ch[c] = neww->ch[c]->add(s, priority, idx + 1); 42 | } 43 | return neww; 44 | } 45 | 46 | StringTrieNode* remove(std::string const& s, int idx=0) { 47 | auto neww = fetch_new(*this); 48 | if (idx == (int)s.size()) { 49 | neww->data = -1; 50 | } else { 51 | int c = s[idx] - 'a'; 52 | if (neww->ch[c]) 53 | neww->ch[c] = neww->ch[c]->remove(s, idx + 1); 54 | } 55 | return neww; 56 | } 57 | 58 | int getData(std::string const& s, int idx=0) { 59 | if (idx == (int)s.size()) { 60 | return data; 61 | } else { 62 | int c = s[idx] - 'a'; 63 | if (ch[c] == nullptr) 64 | return -1; 65 | else 66 | return ch[c]->getData(s, idx+1); 67 | } 68 | } 69 | 70 | int data; 71 | StringTrieNode* ch[26]; 72 | }; 73 | -------------------------------------------------------------------------------- /Trie/StringTrie.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Vertex { 5 | std::array next{}; 6 | bool terminal = false; 7 | }; 8 | 9 | class Trie { 10 | public: 11 | Trie() : t(1) {} 12 | 13 | void add_string(std::string const& s) { 14 | int v = 0; 15 | for (char ch : s) { 16 | int c = ch - 'a'; 17 | if (!t[v].next[c]) { 18 | t[v].next[c] = t.size(); 19 | t.emplace_back(); 20 | } 21 | v = t[v].next[c]; 22 | } 23 | t[v].terminal = true; 24 | } 25 | 26 | private: 27 | std::vector t; 28 | }; 29 | -------------------------------------------------------------------------------- /autoload/alg_ds.vim: -------------------------------------------------------------------------------- 1 | let s:plugin_path = expand(":p:h:h") 2 | 3 | function! alg_ds#AlgDS() 4 | let l:find_cmd = "find . -path '*\\.h' | cut -b3-" 5 | let l:file = join(fzf#run({"source": l:find_cmd, "dir": s:plugin_path, "down": "30%", "options": "--reverse --preview='head -$LINES {}'"})) 6 | if len(l:file) 7 | let l:file_path = s:plugin_path . "/" . l:file 8 | let l:content = readfile(l:file_path) 9 | let l:filtered = alg_ds#Filter(l:content) 10 | put =l:filtered 11 | endif 12 | endfunction 13 | 14 | function! alg_ds#Filter(lines) 15 | " Remove leading includes and empty lines 16 | let l:filtered = [] 17 | let l:started = 0 18 | for line in a:lines 19 | if and(match(line, "\#") != 0, or(l:started, strlen(line) > 0)) 20 | let l:started = 1 21 | call add(l:filtered, line) 22 | endif 23 | endfor 24 | return join(l:filtered, "\n") 25 | endfunction 26 | -------------------------------------------------------------------------------- /demonstration.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakobkogler/Algorithm-DataStructures/f8086642b40cc15f20fbb08fba5ded567773e116/demonstration.gif -------------------------------------------------------------------------------- /plugin/alg_ds.vim: -------------------------------------------------------------------------------- 1 | command! -nargs=0 AlgDS call alg_ds#AlgDS() 2 | -------------------------------------------------------------------------------- /prettyprint.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | def get_vector_element(vec, index): 4 | t = gdb.types.get_basic_type(vec.type) 5 | return gdb.parse_and_eval('(*(%s*)(%s))[%d]' % (t, vec.address, index)) 6 | 7 | def get_vector_size(vec): 8 | eval_string = "(*("+str(vec.type)+"*)("+str(vec.address)+")).size()" 9 | return int(gdb.parse_and_eval(eval_string)) 10 | 11 | class ModularPrinter: 12 | def __init__(self, val): 13 | self.val = val 14 | 15 | def to_string(self): 16 | return str(self.val['value'])# + "m" 17 | 18 | class PolynomialPrinter: 19 | def __init__(self, val): 20 | self.val = val 21 | 22 | def to_string(self): 23 | coeffs = self.val['coeffs'] 24 | l = [] 25 | sz = get_vector_size(coeffs) 26 | for i in range(min(sz, 10)): 27 | elem = get_vector_element(coeffs, i) 28 | l.append(f"{elem}*x^{i}") 29 | if sz > 10: 30 | l.append("...") 31 | return "Polynomial(" + ' + '.join(l) + ")" 32 | 33 | 34 | 35 | def modular_loader(val): 36 | t = str(gdb.types.get_basic_type(val.type)) 37 | if re.match(r"Modular<\d+>", t): 38 | return ModularPrinter(val) 39 | if re.match(r"Polynomial<.*>", t): 40 | return PolynomialPrinter(val) 41 | 42 | gdb.pretty_printers.append(modular_loader) 43 | --------------------------------------------------------------------------------