├── code ├── geometry │ ├── notes.md │ ├── closestpairs.cpp │ ├── jarvis_algorithm.cpp │ ├── collinearpoints.cpp │ └── geometrylib.cpp ├── graphs │ ├── notes.md │ ├── a-star.cpp │ ├── graphlib.cpp │ ├── kruskalsalgorithm.cpp │ ├── kahnsalgorithm.cpp │ ├── floydwarshall.cpp │ ├── bellmanford.cpp │ ├── dijkstra.cpp │ ├── tarjan.cpp │ ├── topologicalsort.cpp │ ├── maxflow.cpp │ └── minspantree.cpp ├── string │ ├── notes.md │ ├── ahocorasick.cpp │ ├── test │ │ └── trie-test.cpp │ └── trie.cpp ├── math │ ├── notes.md │ ├── primesieve.cpp │ ├── gcd_lcm_extended_euclid.cpp │ ├── matrix-det.cpp │ └── matrix-exp.cpp ├── fenwick │ ├── fenwick.md │ ├── fenwick.cpp │ └── fenwick-2d.cpp ├── binary-search │ ├── notes.md │ ├── binary-search.cpp │ └── test │ │ └── binary-search-test1.cpp ├── disjoint-set │ ├── notes.md │ └── unionfind.cpp ├── c++11 │ ├── tuples.cpp │ ├── string_conversions.cpp │ └── lambdas.cpp ├── LIS │ └── LIS.cpp └── segmenttree │ └── segmenttree-2d.cpp ├── output.pdf ├── howto-solve-anything.md ├── hash.py ├── CMakeLists.txt ├── .gitignore ├── test ├── disjoint-set │ ├── unionfind-Kattis-ladice.cpp │ └── unionfind-Kattis-freckles.cpp ├── graphs │ ├── topologicalsort-UVa10305.cpp │ ├── floydwarshall-UVa1233.cpp │ ├── tarjan-UVa11838.cpp │ ├── bellmanford-Kattis-shortestpath3.cpp │ ├── dijkstra-Kattis-shortestpath1.cpp │ ├── kruskalsalgorithm-Kattis-freckles.cpp │ ├── minspantree-Kattis-islandhopping.cpp │ ├── maxflow-Kattis-maxflow.cpp │ └── maxflow-Kattis-elementarymath.cpp ├── string │ └── trie-Kattis-phonelist.cpp ├── LIS │ ├── LIS-Kattis-longincsubseq.cpp │ └── LIS-Kattis-princeandprincess.cpp ├── geometry │ └── collinearpoints.cpp └── segmenttree │ ├── census-UVa11297.cpp │ └── segmenttree-UVa11297.cpp ├── README.md └── latexme.py /code/geometry/notes.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /code/graphs/notes.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /code/string/notes.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /code/geometry/closestpairs.cpp: -------------------------------------------------------------------------------- 1 | // TODO(Unimplemented) 2 | -------------------------------------------------------------------------------- /code/math/notes.md: -------------------------------------------------------------------------------- 1 | GCD, LCM and Extended Euclid is untested -------------------------------------------------------------------------------- /code/fenwick/fenwick.md: -------------------------------------------------------------------------------- 1 | Range query. Log n insert, log n lookup. -------------------------------------------------------------------------------- /code/geometry/jarvis_algorithm.cpp: -------------------------------------------------------------------------------- 1 | // TODO(Unimplemented) 2 | -------------------------------------------------------------------------------- /output.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drathier/compprogcheatsheet/HEAD/output.pdf -------------------------------------------------------------------------------- /code/binary-search/notes.md: -------------------------------------------------------------------------------- 1 | remember lower_bound and upper_bound(begin, end) in stdlib -------------------------------------------------------------------------------- /howto-solve-anything.md: -------------------------------------------------------------------------------- 1 | For when you're tired. 2 | 3 | Approach: 4 | Brute force? 5 | Greedy? 6 | Binary search? 7 | Memoization/dp? 8 | 9 | -------------------------------------------------------------------------------- /code/disjoint-set/notes.md: -------------------------------------------------------------------------------- 1 | does not include rank -> probably O(log(n)). Tofix: empty tree has rank 0. join(a, b) where a.rank==b.rank -> a.rank++, b.parent = a; -------------------------------------------------------------------------------- /code/string/ahocorasick.cpp: -------------------------------------------------------------------------------- 1 | // TODO(Unimplemented) 2 | 3 | // I (drathier) would suggest using a suffix array instead of a suffix tree, since SA is usually faster and way easier to implement than ST -------------------------------------------------------------------------------- /code/graphs/a-star.cpp: -------------------------------------------------------------------------------- 1 | #include dijkstra 2 | 5 inline ValueT dist(const State& s) { return s.first + h(s.first, goal); } 3 | where h does not overestimate distance to goal, and h is preferably monotonic 4 | A* is polynomial if h is within O(log n) of real cost -------------------------------------------------------------------------------- /code/c++11/tuples.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | typedef tuple Tuple; 5 | int main() { 6 | Tuple t = Tuple(1, 2, 3); 7 | cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl; 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /code/fenwick/fenwick.cpp: -------------------------------------------------------------------------------- 1 | void update(vector &tree, int i, T amount) { 2 | for (; i < tree.size(); i |= i + 1) tree[i] += amount; 3 | } 4 | 5 | T sum(const vector &tree, int i) { 6 | T s = T(); 7 | for (; i > 0; i &= i - 1) s += tree[i - 1]; 8 | return s; 9 | } 10 | -------------------------------------------------------------------------------- /hash.py: -------------------------------------------------------------------------------- 1 | __author__ = 'drathier' 2 | 3 | from hashlib import * # md5 2180a11d4d94fd6cc38c36e26e80a594 4 | import fileinput # line-by-line md5 bdaa10d 5 | f = [x.strip() for x in fileinput.input()] 6 | print md5("".join(f)).hexdigest() 7 | print "".join([md5(x).hexdigest()[0] for x in f]) 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(compprogcheatsheet) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 5 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") 6 | 7 | set(SOURCE_FILES 8 | code/math/matrix-det.cpp) 9 | 10 | add_executable(compprogcheatsheet ${SOURCE_FILES}) -------------------------------------------------------------------------------- /code/binary-search/binary-search.cpp: -------------------------------------------------------------------------------- 1 | int search(int n, function lt) { 2 | int i = 0, k = n; 3 | while (i < k) { 4 | int m = i + (k - i) / 2; 5 | if (lt(m)) { // max(lt(m)) s.t. lt(m) is true 6 | i = m + 1; 7 | } else { 8 | k = m; 9 | } 10 | } 11 | return i; // returns where needle SHOULD be! 12 | } -------------------------------------------------------------------------------- /code/math/primesieve.cpp: -------------------------------------------------------------------------------- 1 | vector sieve(int limit) { 2 | vector sieve(limit+1, true); 3 | sieve[0] = sieve[1] = false; 4 | sqlim = sqrt(limit) + 1; 5 | for (int i = 2; i <= sqlim; ++i) { 6 | if (sieve[i]) { 7 | for (int j = i * i; j <= limit; j += i) { 8 | sieve[j] = false; 9 | } 10 | } 11 | } 12 | return sieve; 13 | } 14 | -------------------------------------------------------------------------------- /code/graphs/graphlib.cpp: -------------------------------------------------------------------------------- 1 | typedef int ValueT; 2 | const ValueT INF = 1<<29; 3 | 4 | struct Edge { 5 | int from, to; 6 | ValueT weight; 7 | Edge(int a, int b, ValueT c) {from=a; to=b; weight=c;} 8 | }; 9 | 10 | struct Node { 11 | ValueT dist; 12 | int idx; 13 | bool visited; 14 | Node() {dist=INF; idx=-1; visited=false;} 15 | Node(int i) {dist=INF; idx=i; visited=false;} 16 | }; 17 | -------------------------------------------------------------------------------- /code/c++11/string_conversions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | int main() { 6 | int a_number = 1337; 7 | string a_string = to_string(a_number); 8 | int a_number_again = stoi(a_string); 9 | string my_hex_string = "0xffff"; 10 | stringstream ss; 11 | ss << hex << my_hex_number; 12 | int my_hex_number; 13 | ss >> my_hex_number; 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # jetbrains 3 | .idea/ 4 | 5 | # Compiled Object files 6 | *.slo 7 | *.lo 8 | *.o 9 | *.obj 10 | 11 | # Precompiled Headers 12 | *.gch 13 | *.pch 14 | 15 | # Compiled Dynamic libraries 16 | *.so 17 | *.dylib 18 | *.dll 19 | 20 | # Fortran module files 21 | *.mod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /code/fenwick/fenwick-2d.cpp: -------------------------------------------------------------------------------- 1 | void update(vector> &tree, int i, int k, T amount) { 2 | for (; i < tree.size(); i |= i + 1) { 3 | for (int p = k; p < tree[i].size(); p |= p + 1) { 4 | tree[i][p] += amount; 5 | } 6 | } 7 | } 8 | 9 | T sum(const vector> &tree, int i, int k) { 10 | T s = T(); 11 | for (; i > 0; i &= i - 1) { 12 | for (int p = k; p > 0; p &= p - 1) { 13 | s += tree[i - 1][p - 1]; 14 | } 15 | } 16 | return s; 17 | } -------------------------------------------------------------------------------- /code/graphs/kruskalsalgorithm.cpp: -------------------------------------------------------------------------------- 1 | vector mst(vector& edges, int numNodes) { 2 | priority_queue, EdgeCmp> q(edges.begin(), edges.end()); 3 | UnionFind u(numNodes); 4 | vector ret; 5 | 6 | while (!q.empty()) { 7 | Edge e = q.top(); q.pop(); 8 | if (u.same(e.to, e.from)) { 9 | u.join(e.to, e.from); 10 | ret.push_back(e); 11 | if ((int) ret.size() == numNodes - 1) return ret; 12 | } 13 | } 14 | 15 | return ret; 16 | } -------------------------------------------------------------------------------- /code/graphs/kahnsalgorithm.cpp: -------------------------------------------------------------------------------- 1 | /* Node.dist is used as an "incoming edges"-counter */ 2 | vector topologicalSort(vector& nodes, vector >& adjList) { 3 | vector ret; 4 | for (Node& n : nodes) { 5 | if (n.dist == 0) { 6 | ret.push_back(n); 7 | } 8 | } 9 | for (int i = 0; i < (int) nodes.size(); ++i) { 10 | Node& n = ret[i]; 11 | for (Edge& e : adjList[n.idx]) { 12 | nodes[e.to].dist--; 13 | if (nodes[e.to].dist == 0) ret.push_back(nodes[e.to]); 14 | } 15 | } 16 | return ret; 17 | } -------------------------------------------------------------------------------- /code/c++11/lambdas.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | int main(){ 5 | function prnt = [](int a, int b){cout << a << " and " << b << endl;}; 6 | int the_int = 42; 7 | function prnt2 = [&the_int](int a){cout << a << " THE_INT: " << the_int << endl;}; 8 | int leet = 1337; 9 | function prnt3 = [&](){cout << the_int << " vs. " << leet << endl;}; 10 | function prnt4 = [=](){cout << "Captured by value, not reference" << the_int << leet << endl;}; 11 | } 12 | -------------------------------------------------------------------------------- /code/disjoint-set/unionfind.cpp: -------------------------------------------------------------------------------- 1 | struct UnionFind { 2 | vector parent; 3 | vector rank; 4 | 5 | UnionFind(int size) { 6 | for (int i = 0; i < size; ++i) { 7 | parent.push_back(i); 8 | rank.push_back(0); 9 | } 10 | } 11 | 12 | int root(int i) { 13 | if (parent[i] != i) 14 | parent[i] = root(parent[i]); 15 | return parent[i]; 16 | } 17 | 18 | bool join(int i, int j) { 19 | int p = root(i), q = root(j); 20 | if (p == q) return false; 21 | if (rank[p] < rank[q]) { 22 | parent[p] = q; 23 | } else if (rank[p] > rank[q]) { 24 | parent[q] = p; 25 | } else { 26 | parent[q] = p; 27 | rank[q]++; 28 | } 29 | return true; 30 | } 31 | 32 | bool same(int i, int j) { 33 | return root(i) == root(j); 34 | } 35 | }; -------------------------------------------------------------------------------- /code/math/gcd_lcm_extended_euclid.cpp: -------------------------------------------------------------------------------- 1 | int gcd(int a, int b) { 2 | if (b == 0) return a; 3 | return gcd(b, a%b); 4 | } 5 | 6 | int lcm(int a, int b) { 7 | return abs(a*b) / gcd(a, b); 8 | } 9 | 10 | using i3tuple = tuple; 11 | using i2tuple = tuple; 12 | 13 | i3tuple extendedEuclid(int a, int b) { 14 | if (a == 0) return i3tuple(b, 0, 1); 15 | Tuple t = extendedEuclid(b % a, a); 16 | int _gcd = get<0>(t), x = get<1>(t), y = get<2>(t); 17 | return i3tuple(_gcd, x - (b/a) * y, y); 18 | } 19 | 20 | i2tuple diophanticEquation(int a, int b, int c) { 21 | if (c%gcd(a, b) != 0) return i2tuple(-1, -1); // Unsolvable 22 | i3tuple t = extendedEuclid(a, b); 23 | int _gcd = get<0>(t), x = get<1>(t), y = get<1>(t); 24 | y *= c; x *= c; 25 | return i2tuple(x, y); 26 | } 27 | -------------------------------------------------------------------------------- /code/graphs/floydwarshall.cpp: -------------------------------------------------------------------------------- 1 | const int INF = 1<<31; 2 | const int MAX_V = 101; 3 | const int MAX_E = 10000; 4 | int dist[MAX_V][MAX_V]; 5 | Edge edges[MAX_E]; 6 | void floydWarshall(int size, int num_edge) { 7 | for (int i = 0; i < size; ++i) 8 | for (int j = 0; j < size; ++j) 9 | dist[i][j] = INF; 10 | for (int k = 0; k < size; ++k) {dist[k][k] = 0;} 11 | for (int e = 0; e < num_edge; ++e) { 12 | Edge e = edges[e]; 13 | dist[e.from][e.to] = min(dist[e.from][e.to], e.weight); 14 | } 15 | for (int k = 0; k < size; ++k) { 16 | for (int i = 0; i < size; i++) { 17 | for (int j = 0; j < size; ++j) { 18 | if (dist[i][k] == INF || dist[k][j] == INF) continue; 19 | dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); 20 | /* If solving with negative cycles copy this loop and change the above line to 21 | 'if (dist[k][k] < 0) dist[i][j] = -INF;'*/ 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /code/graphs/bellmanford.cpp: -------------------------------------------------------------------------------- 1 | const int MAX_V = 1005; 2 | const int MAX_E = 5005; 3 | Node nodes[MAX_V]; 4 | Edge edgeList[MAX_E]; 5 | 6 | void bellmanFord(int start, int num_nodes, int num_edges) { 7 | nodes[start].dist = 0; 8 | for (int i = 1; i < num_nodes; ++i) { 9 | for (int k = 0; k < num_edges; ++k) { 10 | const Edge& e = edgeList[k]; 11 | if (nodes[e.from].dist != INF) 12 | nodes[e.to].dist = min(nodes[e.to].dist, 13 | nodes[e.from].dist + e.weight); 14 | } 15 | } 16 | 17 | for (int i = 1; i < num_nodes; ++i) { 18 | for (int k = 0; k < num_edges; ++k) { 19 | const Edge& e = edgeList[k]; 20 | if (nodes[e.from].dist == INF) continue; 21 | 22 | ValueT dist = nodes[e.from].dist + e.weight; 23 | ValueT other = nodes[e.to].dist; 24 | 25 | if (dist < other) 26 | nodes[e.to].dist = -INF; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /code/graphs/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | const int MAX_V = 10005; 2 | Node nodes[MAX_V]; 3 | vector adjList[MAX_V]; 4 | typedef pair State; 5 | inline ValueT dist(const State& s) { return s.first; } 6 | inline int node(const State& s) { return s.second; } 7 | 8 | struct MyCompare { 9 | bool operator() (const State& lhs, const State& rhs) { return dist(lhs) > dist(rhs); } 10 | }; 11 | 12 | void dijkstra(int start) { 13 | priority_queue, MyCompare> pq; 14 | pq.push(State(0, start)); 15 | nodes[start].dist = 0; 16 | while(!pq.empty()) { 17 | State state = pq.top(); pq.pop(); 18 | if (nodes[node(state)].visited) continue; 19 | nodes[node(state)].visited = true; 20 | for (int i = 0; i < (int) adjList[node(state)].size(); ++i){ 21 | const Edge& e = adjList[node(state)][i]; 22 | ValueT next_dist = nodes[e.from].dist + e.weight; 23 | if (next_dist < nodes[e.to].dist) { 24 | nodes[e.to].dist = next_dist; 25 | pq.push(State(next_dist, e.to)); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /code/math/matrix-det.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | using T = long long; 8 | using Row = vector; 9 | using Matrix = vector; 10 | 11 | 12 | T det(const Matrix& a) { // square matrix 13 | if (a.size() == 2 && a[0].size() == 2) { 14 | return a[0][0] * a[1][1] - a[1][0] * a[0][1]; 15 | } 16 | T ret = 0; 17 | for (int i = 0; i < a.size(); i++) { 18 | Matrix tmp(a.size() - 1, Row(a.size() - 1)); 19 | for (int p = 1; p < a.size(); p++) { 20 | for (int k = 0; k < a.size(); k++) { 21 | if (k == i) continue; 22 | tmp[p - 1][k - (k > i)] = a[p][k]; 23 | } 24 | } 25 | ret += a[0][i] * det(tmp) * ((i % 2) * 2 - 1); 26 | } 27 | return ret; 28 | } 29 | 30 | 31 | int main() { 32 | Matrix a({{1, 2, 3}, 33 | {4, 5, 6}, 34 | {7, 8, 9}}); 35 | Matrix b({{7, 8}, 36 | {9, 10}}); 37 | Matrix c({{58, 64}, 38 | {139, 154}}); 39 | Matrix out(a.size(), Row(a[0].size())); 40 | 41 | assert(det(a) == 0); 42 | assert(det(b) == -2); 43 | assert(det(c) == 36); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /test/disjoint-set/unionfind-Kattis-ladice.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | using vi = vector; 5 | 6 | struct UnionFind { 7 | vi parent; 8 | vi rank; 9 | 10 | UnionFind(int size) { 11 | for (int i = 0; i < size; ++i) { 12 | parent.push_back(i); 13 | rank.push_back(0); 14 | } 15 | } 16 | 17 | int root(int i) { 18 | if (parent[i] != i) 19 | parent[i] = root(parent[i]); 20 | return parent[i]; 21 | } 22 | 23 | bool join(int i, int j) { 24 | int p = root(i), q = root(j); 25 | if (p == q) return false; 26 | if (rank[p] < rank[q]) { 27 | parent[p] = q; 28 | } else if (rank[p] > rank[q]) { 29 | parent[q] = p; 30 | } else { 31 | parent[q] = p; 32 | rank[q]++; 33 | } 34 | return true; 35 | } 36 | 37 | bool same(int i, int j) { 38 | return root(i) == root(j); 39 | } 40 | }; 41 | 42 | int main() { 43 | ios::sync_with_stdio(false); 44 | int n, l; cin >> n >> l; 45 | UnionFind u(l+1); 46 | vi empty_boxes(l+1, 1); 47 | for (int i = 0; i < n; ++i) { 48 | int a, b; cin >> a >> b; 49 | if (!u.same(a, b)) { 50 | int sum = empty_boxes[u.root(a)] + empty_boxes[u.root(b)]; 51 | u.join(a, b); 52 | empty_boxes[u.root(a)] = sum; 53 | } 54 | if (empty_boxes[u.root(a)]) { 55 | empty_boxes[u.root(a)]--; 56 | cout << "LADICA" << endl; 57 | } else { 58 | cout << "SMECE" << endl; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CompProgCheatSheet 2 | Cheat sheet for competitive programming 3 | 4 | 5 | # Done 6 | - binary search (tst) 7 | - floyd-warshall (uva) 8 | - bellman-ford (Kattis) 9 | - dijkstra (Kattis) 10 | - topological sort, kahn's algorithm (uva) 11 | - minimum spanning tree, kruskals algorithm (kattis) 12 | - segmenttree 2D (uva) 13 | - matrix exponentiation (non-published impa uva, tst) 14 | - trie (tst) 15 | - matrix determinant (tst) 16 | 17 | # Needs testing 18 | - fenwick tree 19 | - including 2d version 20 | - prime sieve 21 | 22 | # Improvable 23 | - gcd/lcm/eucl/diophantic 24 | - hard to read; would inlining some code (and making a non-recursive version) help? 25 | - A-star 26 | - need to standardize format when including other algorithms 27 | - Matrix exponentiation 28 | - could save around 5 rows of code, and reduce line width by half 29 | 30 | # Todo 31 | - suffix array/tree (aho-corasick) 32 | - suffix array is probably easier to write, and usually faster because of smaller memory footprint 33 | - closest pairs 34 | - convex hull 35 | - jarvis walk or graham scan 36 | - add note about 2x speedup by running top and bottom separately 37 | 38 | - maxflow 39 | - just assume DFS is already done 40 | - strongly connected components 41 | - tarjan or path-based strong component algorithm 42 | - howto solve anything; step by step 43 | - geometry, maths and statistics 44 | - useful formulas and when to use what 45 | - markov chain / MDP 46 | - Ordo-notation for all algorithms, and their limits etc. 47 | - probably best if kept in a table, one per area (graph, string etc.) 48 | -------------------------------------------------------------------------------- /code/graphs/tarjan.cpp: -------------------------------------------------------------------------------- 1 | /* Finds the set of strongly connected components. */ 2 | struct SCCFinder { 3 | SCCFinder(){}; 4 | const int UNEXPLORED = -1; 5 | const int NO_SCC = -1; 6 | 7 | vvi find_sccs(const vvi& adj_list) { 8 | // Reset 9 | num_scc = ticks = 0; 10 | s = stack(); 11 | d = vi(adj_list.size(), UNEXPLORED); 12 | low = vi(adj_list.size()); 13 | scc = vi(adj_list.size(), NO_SCC); 14 | in_stack = vector(adj_list.size(), false); 15 | 16 | // DFS all nodes 17 | for (int a = 0; a < adj_list.size(); ++a) { 18 | if (d[a] == UNEXPLORED) tarjan(adj_list, a); 19 | } 20 | 21 | // Count which scc every node belong to 22 | vvi sccs(num_scc); 23 | for (int i = 0; i < scc.size(); ++i) { 24 | sccs[scc[i]].push_back(i); 25 | } 26 | return sccs; 27 | } 28 | 29 | int num_scc; 30 | int ticks; 31 | vi d, low, scc; 32 | vector in_stack; 33 | stack s; 34 | 35 | void tarjan(const vvi& adj_list, int u) { 36 | d[u] = low[u] = ticks++; 37 | s.push(u); 38 | in_stack[u] = true; 39 | 40 | // Visit all neighbours, carry lowlink up 41 | for (int v : adj_list[u]) { 42 | if (d[v] == UNEXPLORED) { 43 | tarjan(adj_list, v); 44 | low[u] = min(low[u], low[v]); 45 | } else if (in_stack[v]) { 46 | low[u] = min(low[u], low[v]); 47 | } 48 | } 49 | 50 | // If we are the node that started the lowlink 51 | // Pop all nodes visited with dfs and add to scc 52 | if (d[u] == low[u]) { 53 | int v; 54 | do { 55 | v = s.top(); s.pop(); 56 | in_stack[v] = false; 57 | scc[v] = num_scc; 58 | } while(u != v); 59 | num_scc++; 60 | } 61 | } 62 | 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /test/graphs/topologicalsort-UVa10305.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | typedef int ValueT; 6 | const ValueT INF = 1<<29; 7 | 8 | struct Edge { 9 | int from, to; 10 | ValueT weight; 11 | Edge(){from=-1; to=-1; weight=INF;} 12 | Edge(int a, int b, ValueT c) {from=a; to=b; weight=c;} 13 | }; 14 | 15 | struct Node { 16 | ValueT dist; 17 | int idx; 18 | bool visited; 19 | Node(int i=-1, int d=INF){ dist=d; idx=i; visited=false;} 20 | }; 21 | 22 | /* Node.dist is used as an "incoming edges"-counter */ 23 | vector topologicalSort(vector& nodes, vector >& adjList) { 24 | vector ret; 25 | for (Node& n : nodes) { 26 | if (n.dist == 0) { 27 | ret.push_back(n); 28 | } 29 | } 30 | for (int i = 0; i < (int) nodes.size(); ++i) { 31 | Node& n = ret[i]; 32 | for (Edge& e : adjList[n.idx]) { 33 | nodes[e.to].dist--; 34 | if (nodes[e.to].dist == 0) ret.push_back(nodes[e.to]); 35 | } 36 | } 37 | return ret; 38 | } 39 | 40 | void solve(int n, int m) { 41 | vector nodes; 42 | for (int i = 0; i < n; ++i) { 43 | nodes.push_back(Node(i, 0)); 44 | } 45 | vector > edges(n); 46 | for (int i = 0; i < m; ++i) { 47 | int from, to; cin >> from >> to; 48 | from--; to--; // For 0-indexing 49 | Edge edge = Edge(from, to, 0); 50 | edges[from].push_back(edge); 51 | nodes[to].dist++; 52 | } 53 | vector visitOrder = topologicalSort(nodes, edges); 54 | for (Node& n : visitOrder) { 55 | cout << n.idx+1 << " "; 56 | } 57 | cout << endl; 58 | } 59 | 60 | int main() { 61 | ios::sync_with_stdio(false); 62 | int n, m; cin >> n >> m; 63 | for(;n != 0; cin >> n >> m) { 64 | solve(n, m); 65 | } 66 | } -------------------------------------------------------------------------------- /test/graphs/floydwarshall-UVa1233.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The problem solved is p1233 in UVa:s database. 3 | * The basic idea is that the usher sends the thing 4 | * through the same (highest awarding) cycle as many times 5 | * as possible to get the highest value. Then you remove the number of 6 | * times that the usher gets the thing back. 7 | */ 8 | #include 9 | using namespace std; 10 | 11 | constexpr int min(int a, int b) { return a < b ? a : b; } 12 | 13 | int solve(int b, int p) 14 | { 15 | int capacity = b, parishioners = p; 16 | int Graph[parishioners+1][parishioners+1]; 17 | for (int r = 0; r <= parishioners; ++r) { 18 | for (int c = 0; c <= parishioners; c++) { 19 | Graph[r][c] = INF; 20 | } 21 | } 22 | 23 | int usherEdges; cin >> usherEdges; 24 | for (int k = 0; k < usherEdges; k++) { 25 | int tmp; cin >> tmp; 26 | Graph[0][tmp] = 0; 27 | } 28 | 29 | // Edges are represented directly in the graph 30 | for (int i = 1; i <= parishioners; ++i) { 31 | int edges; cin >> edges; 32 | for (;edges--;) { 33 | int cost, to; cin >> cost >> to; 34 | Graph[i][to] = min(Graph[i][to], cost); 35 | } 36 | } 37 | 38 | for (int k = 0; k <= parishioners; ++k) 39 | for (int i = 0; i <= parishioners; ++i) 40 | for (int j = 0; j <= parishioners; ++j) 41 | Graph[i][j] = min(Graph[i][j], Graph[i][k] + Graph[k][j]); 42 | 43 | int bestCost = Graph[0][0]; 44 | int answer = 0, current = 0; 45 | while (true) { 46 | if ((current += bestCost) >= capacity) break; 47 | current--; 48 | answer++; 49 | } 50 | 51 | return answer; 52 | } 53 | 54 | int main() 55 | { 56 | ios::sync_with_stdio(false); 57 | int TC; cin >> TC; 58 | while (TC--) { 59 | int b, p; cin >> b >> p; 60 | cout << solve(b, p) << endl; 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /code/string/test/trie-test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | typedef string T; 10 | 11 | // does not deduplicate input 12 | // wastes space; stores n pointers per insert 13 | // leaks memory 14 | struct trie { 15 | trie *next[256] = {}; 16 | vector things; 17 | 18 | void insert(string s, int p, T *thing) { 19 | this->things.push_back(thing); 20 | if (next[s[p]] == nullptr) 21 | next[s[p]] = new trie(); 22 | if (p < s.size()) 23 | next[s[p]]->insert(s, p + 1, thing); 24 | } 25 | 26 | vector find(string s, int p) { 27 | if (p == s.size()) 28 | return things; 29 | if (next[s[p]] != nullptr) 30 | return next[s[p]]->find(s, p + 1); 31 | return vector(); 32 | } 33 | }; 34 | 35 | 36 | int main() { 37 | trie t; 38 | T seven = "7"; 39 | T two = "2"; 40 | T sixteen = "16"; 41 | T fourtytwo = "42"; 42 | T thirtyseven = "37"; 43 | t.insert("hejsan", 0, &seven); 44 | t.insert("hejsan", 0, &two); 45 | t.insert("hejsan", 0, &sixteen); 46 | t.insert("hej", 0, &fourtytwo); 47 | t.insert("hejsan", 0, &seven); // again 48 | t.insert("hej", 0, &thirtyseven); 49 | assert(t.find("", 0) == vector({&seven, &two, &sixteen, &fourtytwo, &seven, &thirtyseven})); 50 | assert(t.find("hej", 0) == vector({&seven, &two, &sixteen, &fourtytwo, &seven, &thirtyseven})); 51 | assert(t.find("hejs", 0) == vector({&seven, &two, &sixteen, &seven})); 52 | assert(t.find("hejsan", 0) == vector({&seven, &two, &sixteen, &seven})); 53 | assert(t.find("heja", 0) == vector()); 54 | assert(t.find("", 4711) == vector()); 55 | assert(t.find("heja", 0) != vector({&sixteen})); 56 | 57 | trie t2; 58 | assert(t2.find("", 0) == vector()); 59 | assert(t2.find("", 4711) == vector()); 60 | assert(t2.find("hej", 0) == vector()); 61 | } -------------------------------------------------------------------------------- /code/graphs/topologicalsort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | // Sometimes you might want to have a map 4 | // instead of a vector because of the number of possible nodes 5 | // are different (see https://open.kattis.com/problems/parallelanalysis) 6 | // In that case the numbers will be integers between [0, 2^31 - 1] 7 | // But this is mostly not the case. 8 | // Change the definition here and wherever deps/adj_list is assigned to. 9 | using vi = vector; 10 | using vvi = vector; 11 | 12 | class Toposorter { 13 | private: 14 | vi deps; 15 | vvi adj_list; 16 | 17 | public: 18 | 19 | Toposorter(int num_nodes) { 20 | deps = vi(num_nodes); 21 | adj_list = vvi(num_nodes); 22 | }; 23 | 24 | void reset() { 25 | const int num_nodes = deps.size(); 26 | deps = vi(num_nodes); 27 | adj_list = vvi(num_nodes); 28 | } 29 | 30 | // e.from has to be done before e.to 31 | void run(const vector& dependencies) { 32 | for (const Edge& e : dependencies) { 33 | deps[e.to]++; 34 | adj_list[e.from].push_back(e.to); 35 | } 36 | } 37 | 38 | vi topological_order() { 39 | const int num_nodes = deps.size(); 40 | vi the_deps(deps); 41 | vi order; 42 | 43 | for (int i = 0; i < num_nodes; ++i) { 44 | if (the_deps[i] == 0) order.push_back(i); 45 | } 46 | 47 | for (int i = 0; i < order.size(); ++i) { 48 | int now = order[i]; 49 | for (int neigh : adj_list[now]) { 50 | the_deps[neigh]--; 51 | if (the_deps[neigh] == 0) { 52 | order.push_back(neigh); 53 | } 54 | } 55 | } 56 | 57 | return order; 58 | } 59 | 60 | vi dependencies() {return deps;} 61 | vvi adjacency_list() {return adj_list;} 62 | }; 63 | -------------------------------------------------------------------------------- /code/LIS/LIS.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | using vi=vector; 7 | 8 | // Find the length maximal j such that seq[best[j]] < target 9 | int binary_search(const vi& seq, const vi& best, 10 | int low, int high, int target) { 11 | auto holds = [&](int a) { 12 | return seq[best[a]] < target; 13 | }; 14 | 15 | for (int middle = (low+high)/2; high - low > 1; middle=(low+high)/2) 16 | holds(middle) ? low = middle : high = middle - 1; 17 | 18 | if (holds(high)) return high; 19 | else if (holds(low)) return low; 20 | else return 0; // Nothing is smaller than this (to the left) 21 | } 22 | 23 | // Returns the parent vector and the index to the last element in the 24 | // longest sequence. 25 | tuple longest_increasing_subsequence(const vi& seq) { 26 | int best_length = 1; 27 | vi current_best(seq.size() + 1); 28 | current_best[1] = 0; 29 | vi parent(seq.size()); 30 | for (int i = 0; i < seq.size(); ++i) parent[i] = i; 31 | 32 | // For every number except the first one, find The maximum j such 33 | // that j < i && seq[j] < seq[i]. We do this by binary searching 34 | // over the length of the "previous" LIS. We keep a tab on where 35 | // each longest subsequence is by using the "current_best" vector. 36 | 37 | for (int i = 1; i < seq.size(); ++i) { 38 | int len = binary_search(seq, current_best, 1, best_length, seq[i]); 39 | 40 | if (len == 0) { 41 | parent[i] = i; 42 | } else { 43 | parent[i] = current_best[len]; 44 | } 45 | 46 | const int len_with_this = len + 1; 47 | 48 | if (len_with_this > best_length || 49 | seq[i] < seq[current_best[len_with_this]]) { 50 | current_best[len_with_this] = i; 51 | best_length = max(len_with_this, best_length); 52 | } 53 | } 54 | 55 | return tuple(parent, current_best[best_length]); 56 | } 57 | -------------------------------------------------------------------------------- /code/string/trie.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct Trie { 5 | 6 | // Nodes can use vectors but that would eat up a lot of space. 7 | // Now they are slow instead. 8 | struct Node { 9 | char letter; 10 | bool ends_here; 11 | map children; 12 | Node() : letter('-'), ends_here(false) {} 13 | Node(char c) : letter(c), ends_here(false) {} 14 | bool has_child(char c) {return children.find(c) != children.end();} 15 | 16 | void add_string(const string& s, int pos) { 17 | if (pos == s.size()) { 18 | ends_here = true; 19 | return; 20 | } else { 21 | const char current = s[pos]; 22 | if (!has_child(current)) { 23 | children[current] = Node(current); 24 | } 25 | children[current].add_string(s, pos + 1); 26 | } 27 | } 28 | 29 | bool prefix(const string& s, int pos) { 30 | // To check if there exists a prefix to 's': 31 | //if (ends_here) { 32 | // To check if 's' is a prefix to something in the trie: 33 | //if (pos == s.size()) 34 | // Both: 35 | if (ends_here or pos == s.size()) { 36 | return true; 37 | } else { 38 | if (!has_child(s[pos])) return false; 39 | else return children[s[pos]].prefix(s, pos+1); 40 | } 41 | } 42 | }; 43 | 44 | Node root; 45 | 46 | // Returns true if this is a prefix to some word 47 | // or if there is a word that is a prefix to this. 48 | bool prefix(const string& s) { 49 | return root.prefix(s, 0); 50 | } 51 | 52 | void add_string(const string& s) { 53 | if (s.size() == 0) return; 54 | root.add_string(s, 0); 55 | } 56 | 57 | }; 58 | -------------------------------------------------------------------------------- /code/graphs/maxflow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | using T = long long; 4 | using vi=vector< int >; 5 | using vvi=vector< vi >; 6 | 7 | /** It is important to create the adjecency list with bidirectional edges*/ 8 | 9 | const int INF = 100000; 10 | const int UNDEF = -1; 11 | 12 | int SINK = UNDEF; 13 | int SOURCE = UNDEF; 14 | 15 | bool has_aug_path(vvi& flow_graph, vvi& adjacency_list, vi& parent) { 16 | vvi& adj = adjacency_list; 17 | 18 | int s = SOURCE, t = SINK; 19 | vector visited(flow_graph.size(), false); 20 | queue q; 21 | q.push(s); 22 | parent[s] = UNDEF; 23 | visited[s] = true; 24 | 25 | while (!q.empty()) { 26 | int now = q.front(); q.pop(); 27 | 28 | for (int neighbour : adj[now]) { 29 | const int n = neighbour; 30 | if (!visited[n] && flow_graph[now][n] > 0) { 31 | parent[n] = now; 32 | visited[n] = true; 33 | q.push(n); 34 | if (n == t) { 35 | return true; 36 | } 37 | } 38 | } 39 | } 40 | 41 | return false; 42 | } 43 | 44 | // Flow graph == Residual graph with capacities applied 45 | int max_flow(vvi& flow_graph, vvi& adjacency_list, int source, int sink) { 46 | SOURCE = source; 47 | SINK = sink; 48 | vi parent(flow_graph.size()); 49 | 50 | int maximum = 0; 51 | while (has_aug_path(flow_graph, adjacency_list, parent)) { 52 | int flow = INF; 53 | 54 | // Search through path for limiting flow 55 | for (int current = SINK; current != SOURCE; current = parent[current]) { 56 | int p = parent[current]; 57 | flow = min(flow, flow_graph[p][current]); 58 | } 59 | 60 | // Fill path with limiting flow 61 | for (int current = SINK; current != SOURCE; current = parent[current]) { 62 | int p = parent[current]; 63 | flow_graph[p][current] -= flow; 64 | flow_graph[current][p] += flow; 65 | } 66 | 67 | maximum += flow; 68 | } 69 | 70 | return maximum; 71 | } 72 | -------------------------------------------------------------------------------- /code/graphs/minspantree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | /** 3 | * Needs union find for its implementation. 4 | */ 5 | 6 | /** 7 | * Interface 8 | */ 9 | class DisjointSet { 10 | public: 11 | DisjointSet(int size); 12 | 13 | void join(int a, int b); 14 | int findRoot(int i); 15 | bool sameSet(int a, int b); 16 | 17 | private: 18 | std::vector parent; 19 | std::vector rank; 20 | }; 21 | 22 | /** 23 | * Implementation 24 | */ 25 | DisjointSet::DisjointSet(int size) { 26 | parent = std::vector(size); 27 | rank = std::vector(size); 28 | for (int i = 0; i < size; ++i) { 29 | parent[i] = i; 30 | } 31 | } 32 | 33 | int DisjointSet::findRoot(int i) { 34 | return i != parent[i] ? (parent[i] = findRoot(parent[i])) : parent[i]; 35 | } 36 | 37 | void DisjointSet::join(int a, int b) { 38 | int i = findRoot(b), j = findRoot(a); 39 | if (i != j) { 40 | if (rank[i] > rank[j]) { 41 | parent[j] = i; 42 | } else { 43 | parent[i] = j; 44 | } 45 | if (rank[i] == rank[j]) rank[i]++; 46 | } 47 | } 48 | 49 | inline bool DisjointSet::sameSet(int a, int b) { 50 | return findRoot(a) == findRoot(b); 51 | } 52 | 53 | using namespace std; 54 | 55 | using ValueT=double; 56 | struct Edge { 57 | int u, v; 58 | ValueT w; 59 | }; 60 | using ve = vector; 61 | 62 | bool edge_compare(const Edge& lhs, const Edge& rhs) { 63 | return lhs.w < rhs.w; 64 | } 65 | 66 | tuple solve(ve& edges, int nodes) { 67 | sort(edges.begin(), edges.end(), edge_compare); 68 | ve tree; 69 | DisjointSet ds(nodes); 70 | ValueT sum = 0; 71 | for (Edge e : edges) { 72 | if (!ds.sameSet(e.u, e.v)) { 73 | ds.join(e.u, e.v); 74 | tree.push_back(e); 75 | sum += e.w; 76 | } else if (tree.size() == nodes - 1) { 77 | break; 78 | } 79 | } 80 | return tuple{tree, sum}; 81 | } 82 | -------------------------------------------------------------------------------- /test/graphs/tarjan-UVa11838.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | using vi=vector; 6 | using vvi=vector; 7 | 8 | struct SCCFinder { 9 | 10 | SCCFinder(){}; 11 | 12 | void reset() { 13 | d.clear(); 14 | low.clear(); 15 | scc.clear(); 16 | while (!s.empty()) s.pop(); 17 | in_stack.clear(); 18 | num_scc = ticks = 0; 19 | } 20 | 21 | vvi find_sccs(vvi& adj_list) { 22 | reset(); 23 | d = vi(adj_list.size(), -1); 24 | low = vi(adj_list.size()); 25 | scc = vi(adj_list.size(), -1); 26 | in_stack = vector(adj_list.size(), false); 27 | for (int a = 0; a < adj_list.size(); ++a) { 28 | if (d[a] == -1) tarjan(adj_list, a); 29 | } 30 | 31 | vvi sccs(num_scc); 32 | for (int i = 0; i < scc.size(); ++i) { 33 | sccs[scc[i]].push_back(i); 34 | } 35 | return sccs; 36 | } 37 | 38 | int num_scc; 39 | int ticks; 40 | vi d, low, scc; 41 | vector in_stack; 42 | stack s; 43 | 44 | void tarjan(vvi& adj_list, int u) { 45 | d[u] = low[u] = ticks++; 46 | s.push(u); 47 | in_stack[u] = true; 48 | 49 | for (int v : adj_list[u]) { 50 | if (d[v] == -1) { 51 | tarjan(adj_list, v); 52 | low[u] = min(low[u], low[v]); 53 | } else if (in_stack[v]) { 54 | low[u] = min(low[u], low[v]); 55 | } 56 | } 57 | 58 | if (d[u] == low[u]) { 59 | int v; 60 | do { 61 | v = s.top(); s.pop(); 62 | in_stack[v] = false; 63 | scc[v] = num_scc; 64 | } while(u != v); 65 | num_scc++; 66 | } 67 | } 68 | 69 | }; 70 | 71 | SCCFinder sf; 72 | int main() { 73 | int n, m; cin >> n >> m; 74 | for (; n != 0; cin >> n >> m) { 75 | vvi adj(n); 76 | for (int i = 0; i < m; ++i) { 77 | int a, b, type; cin >> a >> b >> type; 78 | a--; b--; 79 | adj[a].push_back(b); 80 | if (type == 2) adj[b].push_back(a); 81 | } 82 | 83 | vvi sccs = sf.find_sccs(adj); 84 | if (sccs.size() == 1) { 85 | cout << "1" << endl; 86 | } else { 87 | cout << "0" << endl; 88 | } 89 | 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /test/graphs/bellmanford-Kattis-shortestpath3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | typedef int ValueT; 6 | const ValueT INF = 1<<29; 7 | 8 | struct Edge { 9 | int from, to; 10 | ValueT weight; 11 | Edge(){from=-1; to=-1; weight=INF;} 12 | Edge(int a, int b, ValueT c) {from=a; to=b; weight=c;} 13 | }; 14 | 15 | struct Node { 16 | ValueT dist; 17 | int idx; 18 | bool visited; 19 | Node() {dist=INF; idx=-1; visited=false;} 20 | Node(int i){ dist=INF; idx=i; visited=false;} 21 | }; 22 | 23 | const int MAX_V = 1005; 24 | const int MAX_E = 5005; 25 | Node nodes[MAX_V]; 26 | Edge edgeList[MAX_E]; 27 | 28 | void bellmanFord(int start, int num_nodes, int num_edges) { 29 | nodes[start].dist = 0; 30 | for (int i = 1; i < num_nodes; ++i) { 31 | for (int k = 0; k < num_edges; ++k) { 32 | const Edge& e = edgeList[k]; 33 | if (nodes[e.from].dist != INF) 34 | nodes[e.to].dist = min(nodes[e.to].dist, nodes[e.from].dist + e.weight); 35 | } 36 | } 37 | 38 | for (int i = 1; i < num_nodes; ++i) { 39 | for (int k = 0; k < num_edges; ++k) { 40 | const Edge& e = edgeList[k]; 41 | if (nodes[e.from].dist == INF) continue; 42 | 43 | ValueT dist = nodes[e.from].dist + e.weight; 44 | ValueT other = nodes[e.to].dist; 45 | 46 | if (dist < other) 47 | nodes[e.to].dist = -INF; 48 | } 49 | } 50 | } 51 | 52 | int main() { 53 | ios::sync_with_stdio(false); 54 | int n, m, q, s; 55 | cin >> n >> m >> q >> s; 56 | int first = 0; 57 | for (; n != 0; cin >> n >> m >> q >> s) { 58 | if (first++ != 0) 59 | cout << endl; 60 | for (int k = 0; k < n; ++k) { 61 | nodes[k] = Node(k); 62 | } 63 | for (int k = 0; k < m; ++k) { 64 | int a, b, c; cin >> a >> b >> c; 65 | edgeList[k] = Edge(a, b, c); 66 | } 67 | bellmanFord(s, n, m); 68 | for (int i = 0; i < q; ++i) { 69 | int k; cin >> k; 70 | if (nodes[k].dist == INF) cout << "Impossible" << endl; 71 | else if (nodes[k].dist == -INF) cout << "-Infinity" << endl; 72 | else cout << nodes[k].dist << endl; 73 | } 74 | 75 | } 76 | } -------------------------------------------------------------------------------- /test/graphs/dijkstra-Kattis-shortestpath1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | typedef int ValueT; 8 | const ValueT INF = 1<<29; 9 | 10 | struct Edge { 11 | int from, to; 12 | ValueT weight; 13 | Edge(int a, int b, ValueT c) {from=a; to=b; weight=c;} 14 | }; 15 | 16 | struct Node { 17 | ValueT dist; 18 | int idx; 19 | bool visited; 20 | Node() {dist=INF; idx=-1; visited=false;} 21 | Node(int i){ dist=INF; idx=i; visited=false;} 22 | }; 23 | 24 | const int MAX_V = 10005; 25 | Node nodes[MAX_V]; 26 | vector adjList[MAX_V]; 27 | typedef tuple State; 28 | inline ValueT dist(const State& s) { return get<0>(s); } 29 | inline int node(const State& s) { return get<1>(s); } 30 | 31 | struct MyCompare { 32 | bool operator() (const State& lhs, const State& rhs) { return dist(lhs) > dist(rhs); } 33 | }; 34 | 35 | void dijkstra(int start) { 36 | priority_queue, MyCompare> pq; 37 | pq.push(State(0, start)); 38 | nodes[start].dist = 0; 39 | while(!pq.empty()) { 40 | State state = pq.top(); pq.pop(); 41 | if (nodes[node(state)].visited) continue; 42 | nodes[node(state)].visited = true; 43 | for (int i = 0; i < (int) adjList[node(state)].size(); ++i){ 44 | const Edge& e = adjList[node(state)][i]; 45 | ValueT next_dist = nodes[e.from].dist + e.weight; 46 | if (next_dist < nodes[e.to].dist) { 47 | nodes[e.to].dist = next_dist; 48 | pq.push(State(next_dist, e.to)); 49 | } 50 | } 51 | } 52 | } 53 | 54 | int main() { 55 | ios::sync_with_stdio(false); 56 | int n, m, q, s; 57 | cin >> n >> m >> q >> s; 58 | int first = 0; 59 | for (; n != 0; cin >> n >> m >> q >> s) { 60 | if (first++ != 0) 61 | cout << endl; 62 | for (int k = 0; k < n; ++k) { 63 | nodes[k] = Node(k); 64 | adjList[k].clear(); 65 | } 66 | for (int k = 0; k < m; ++k) { 67 | int a, b, c; cin >> a >> b >> c; 68 | adjList[a].push_back(Edge(a, b, c)); 69 | } 70 | dijkstra(s); 71 | for (int i = 0; i < q; ++i) { 72 | int k; cin >> k; 73 | if (nodes[k].dist == INF) cout << "Impossible" << endl; 74 | else cout << nodes[k].dist << endl; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /code/math/matrix-exp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | using T = long long; 9 | using Row = vector; 10 | using Matrix = vector; 11 | 12 | void matmul(Matrix &a, Matrix &b, Matrix &out, T mod = LLONG_MAX / 2) { // assuming (row,col) and a.size = b[0].size() 13 | for (int i = 0; i < a.size(); i++) { 14 | for (int k = 0; k < b[0].size(); k++) 15 | out[i][k] = 0; // reset 16 | for (int h = 0; h < b.size(); h++) { 17 | for (int k = 0; k < b[0].size(); k++) { 18 | out[i][k] = (out[i][k] + a[i][h] * b[h][k]) % mod; // loop order important for cache hits 19 | } 20 | } 21 | } 22 | } 23 | 24 | void matpow(Matrix &a, T n, Matrix &out, T mod = LLONG_MAX / 2) { // out=(a^n)%mod assuming square matrix and out filled with zeroes. 25 | for (int i = 0; i < out.size(); i++) 26 | out[i][i] = 1; // out = identity matrix 27 | Matrix tmp(a.size(), Row(a[0].size())); 28 | while (n > 0) { 29 | if (n & 1) { 30 | matmul(out, a, tmp, mod); 31 | for (int i = 0; i < tmp.size(); i++) 32 | for (int k = 0; k < tmp[0].size(); k++) 33 | out[i][k] = tmp[i][k]; 34 | } 35 | matmul(a, a, tmp, mod); 36 | for (int i = 0; i < tmp.size(); i++) 37 | for (int k = 0; k < tmp[0].size(); k++) 38 | a[i][k] = tmp[i][k]; 39 | n = n / 2; 40 | } 41 | } 42 | 43 | void print(Matrix &a) { 44 | for (int i = 0; i < a.size(); i++) { 45 | for (int k = 0; k < a[i].size(); k++) { 46 | cout << a[i][k] << " "; 47 | } 48 | cout << endl; 49 | } 50 | } 51 | 52 | /* 53 | * not handled: 54 | * mul of matrix of invalid sizes 55 | * 56 | * tested: 57 | * basic matmul 58 | * basic matpow for fib(n) 59 | * 60 | * not tested: 61 | * mod 62 | * 63 | * todo: 64 | * short text about how to find the matrix to exponentiate 65 | * */ 66 | 67 | int main() { 68 | Matrix a({{1, 2, 3}, 69 | {4, 5, 6}}); 70 | Matrix b({{7, 8}, 71 | {9, 10}, 72 | {11, 12}}); 73 | Matrix ab({{58, 64}, 74 | {139, 154}}); 75 | Matrix out(b[0].size(), Row(a.size())); 76 | matmul(a, b, out); 77 | assert(out == ab); 78 | matmul(a, b, out); 79 | assert(out == ab); 80 | 81 | // matpow test: fibonacci 82 | Matrix fib({{1, 1}, 83 | {1, 0}}); 84 | Matrix res({{0, 0}, 85 | {0, 0}}); 86 | T n = 13; 87 | matpow(fib, n - 2, res); 88 | assert(res[0][0] == 144); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /test/string/trie-Kattis-phonelist.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct Trie { 5 | 6 | // Nodes can use vectors but that would eat up a lot of space. 7 | // Now they are slow instead. 8 | struct Node { 9 | char letter; 10 | bool ends_here; 11 | map children; 12 | Node() : letter('-'), ends_here(false) {} 13 | Node(char c) : letter(c), ends_here(false) {} 14 | bool has_child(char c) {return children.find(c) != children.end();} 15 | 16 | void add_string(const string& s, int pos) { 17 | if (pos == s.size()) { 18 | ends_here = true; 19 | return; 20 | } else { 21 | const char current = s[pos]; 22 | if (!has_child(current)) { 23 | children[current] = Node(current); 24 | } 25 | children[current].add_string(s, pos + 1); 26 | } 27 | } 28 | 29 | bool prefix(const string& s, int pos) { 30 | // To check if there exists a prefix to 's': 31 | //if (ends_here) { 32 | // To check if 's' is a prefix to something in the trie: 33 | //if (pos == s.size()) 34 | // Both: 35 | if (ends_here or pos == s.size()) { 36 | return true; 37 | } else { 38 | if (!has_child(s[pos])) return false; 39 | else return children[s[pos]].prefix(s, pos+1); 40 | } 41 | } 42 | }; 43 | 44 | Node root; 45 | 46 | // Returns true if this is a prefix to some word 47 | // or if there is a word that is a prefix to this. 48 | bool prefix(const string& s) { 49 | return root.prefix(s, 0); 50 | } 51 | 52 | void add_string(const string& s) { 53 | if (s.size() == 0) return; 54 | root.add_string(s, 0); 55 | } 56 | 57 | }; 58 | 59 | 60 | void solve(const vector& numbers) { 61 | Trie trie; 62 | for (const string& s : numbers) { 63 | if (trie.prefix(s)) { 64 | cout << "NO" << endl; 65 | return; 66 | } 67 | trie.add_string(s); 68 | } 69 | cout << "YES" << endl; 70 | } 71 | 72 | 73 | int main() { 74 | ios::sync_with_stdio(false); 75 | int t, n; 76 | cin >> t; 77 | while (t--) { 78 | cin >> n; 79 | vector numbers(n); 80 | for (string& s : numbers) cin >> s; 81 | solve(numbers); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /test/LIS/LIS-Kattis-longincsubseq.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | using vi=vector; 5 | 6 | // Find the length maximal j such that seq[best[j]] < target 7 | int binary_search(const vi& seq, const vi& best, 8 | int low, int high, int target) { 9 | auto holds = [&](int a) { 10 | return seq[best[a]] < target; 11 | }; 12 | 13 | for (int middle = (low+high)/2; high - low > 1; middle=(low+high)/2) 14 | holds(middle) ? low = middle : high = middle - 1; 15 | 16 | if (holds(high)) return high; 17 | else if (holds(low)) return low; 18 | else return 0; // Nothing is smaller than this (to the left) 19 | } 20 | 21 | // Returns the parent vector and the index to the last element in the 22 | // longest sequence. 23 | tuple longest_increasing_subsequence(const vi& seq) { 24 | int best_length = 1; 25 | vi current_best(seq.size() + 1); 26 | current_best[1] = 0; 27 | vi parent(seq.size()); 28 | for (int i = 0; i < seq.size(); ++i) parent[i] = i; 29 | 30 | // For every number except the first one, find The maximum j such 31 | // that j < i && seq[j] < seq[i]. We do this by binary searching 32 | // over the length of the "previous" LIS. We keep a tab on where 33 | // each longest subsequence is by using the "current_best" vector. 34 | 35 | for (int i = 1; i < seq.size(); ++i) { 36 | int len = binary_search(seq, current_best, 1, best_length, seq[i]); 37 | 38 | if (len == 0) { 39 | parent[i] = i; 40 | } else { 41 | parent[i] = current_best[len]; 42 | } 43 | 44 | const int len_with_this = len + 1; 45 | 46 | if (len_with_this > best_length || 47 | seq[i] < seq[current_best[len_with_this]]) { 48 | current_best[len_with_this] = i; 49 | best_length = max(len_with_this, best_length); 50 | } 51 | } 52 | 53 | return tuple(parent, current_best[best_length]); 54 | } 55 | 56 | int main() { 57 | ios::sync_with_stdio(false); 58 | int n; 59 | while (cin >> n) { 60 | vector seq(n); 61 | for (int i = 0; i < n; ++i) cin >> seq[i]; 62 | 63 | tuple tp = longest_increasing_subsequence(seq); 64 | vi parent = get<0>(tp); 65 | int best = get<1>(tp); 66 | 67 | vi output; 68 | for (; parent[best] != best; best = parent[best]) 69 | output.push_back(best); 70 | output.push_back(best); 71 | 72 | cout << output.size() << endl; 73 | for (auto it = output.rbegin(); it != output.rend(); ++it) 74 | cout << *it << " "; 75 | cout << endl; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /test/graphs/kruskalsalgorithm-Kattis-freckles.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | struct UnionFind { 9 | vector parents; 10 | vector rank; 11 | 12 | UnionFind(int size) { 13 | for (int i = 0; i < size; ++i) { 14 | parents.push_back(i); 15 | rank.push_back(0); 16 | } 17 | } 18 | 19 | int root(int i) { 20 | if (parent[i] != i) 21 | parent[i] = root(parent[i]); 22 | return parent[i]; 23 | } 24 | 25 | bool join(int i, int j) { 26 | int p = root(i), q = root(j); 27 | if (p == q) return false; 28 | if (rank[p] < rank[q]) { 29 | parent[p] = q; 30 | } else if (rank[p] > rank[q]) { 31 | parent[q] = p; 32 | } else { 33 | parent[q] = p; 34 | rank[q]++; 35 | } 36 | return true; 37 | } 38 | 39 | bool same(int i, int j) { 40 | return root(i) == root(j); 41 | } 42 | }; 43 | 44 | struct Node { 45 | double x, y; 46 | Node(double a, double b) {x = a; y = b;} 47 | double dist(Node& other) 48 | {return sqrt((x-other.x)*(x-other.x) + (y-other.y)*(y-other.y));} 49 | }; 50 | 51 | struct Edge { 52 | int from, to; 53 | double weight; 54 | Edge(int a, int b, double c=double()) { 55 | from = a; to = b; weight = c; 56 | } 57 | }; 58 | 59 | struct EdgeCmp { 60 | bool operator()(Edge& e1, Edge& e2) { 61 | return e1.weight > e2.weight; 62 | } 63 | }; 64 | 65 | vector mst(vector& edges, int numNodes) { 66 | priority_queue, EdgeCmp> q(edges.begin(), edges.end()); 67 | UnionFind u(numNodes); 68 | vector ret; 69 | 70 | while (!q.empty()) { 71 | Edge e = q.top(); q.pop(); 72 | if (u.same(e.to, e.from)) { 73 | u.join(e.to, e.from); 74 | ret.push_back(e); 75 | if ((int) ret.size() == numNodes - 1) return ret; 76 | } 77 | } 78 | return ret; 79 | } 80 | 81 | int main() { 82 | ios::sync_with_stdio(false); 83 | cout << fixed << setprecision(2); 84 | int TC; cin >> TC; 85 | while (TC--) { 86 | int n; cin >> n; 87 | 88 | vector nodes; 89 | for (int i = 0; i < n; ++i) { 90 | double a, b; cin >> a >> b; 91 | nodes.push_back(Node(a, b)); 92 | } 93 | 94 | vector edges; 95 | for (int i = 0; i < n; ++i) { 96 | for (int j = i+1; j < n; ++j) { 97 | double d = nodes[i].dist(nodes[j]); 98 | edges.push_back(Edge(i, j, d)); 99 | } 100 | } 101 | vector myMst = mst(edges, n); 102 | double sum = 0; 103 | for (Edge& e : myMst) sum += e.weight; 104 | cout << sum << "\n\n"; 105 | } 106 | } 107 | 108 | -------------------------------------------------------------------------------- /code/binary-search/test/binary-search-test1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | vector data{-10, -5, 0, 1, 2, 3, 5, 7, 11, 100, 100, 100, 1000, 10000}; 9 | vector data_desc{99, 99, 59, 42, 7, 0, -1, -1}; 10 | 11 | int search(int n, function lt) { 12 | int i = 0, k = n; 13 | while (i < k) { 14 | int m = i + (k - i) / 2; 15 | if (lt(m)) { // max(lt(m)) s.t. lt(m) is true 16 | i = m + 1; 17 | } else { 18 | k = m; 19 | } 20 | } 21 | return i; // returns where needle SHOULD be! 22 | } 23 | 24 | int main() { 25 | assert(search(0, function([](int a) { return a < 0; })) == 0); 26 | assert(search(1, function([](int a) { return a < 1; })) == 1); 27 | assert(search(1, function([](int a) { return false; })) == 0); 28 | assert(search(1, function([](int a) { return true; })) == 1); 29 | assert(search(1e9, function([](int a) { return a < 991; })) == 991); 30 | assert(search(1e9, function([](int a) { return false; })) == 0); 31 | assert(search(1e9, function([](int a) { return true; })) == 1e9); 32 | assert(search(data.size(), function([](int a) { return data.at(a) < -20; })) == 0); 33 | assert(search(data.size(), function([](int a) { return data.at(a) < -10; })) == 0); 34 | assert(search(data.size(), function([](int a) { return data.at(a) < -9; })) == 1); 35 | assert(search(data.size(), function([](int a) { return data.at(a) < -6; })) == 1); 36 | assert(search(data.size(), function([](int a) { return data.at(a) < -5; })) == 1); 37 | assert(search(data.size(), function([](int a) { return data.at(a) < 3; })) == 5); 38 | assert(search(data.size(), function([](int a) { return data.at(a) < 11; })) == 8); 39 | assert(search(data.size(), function([](int a) { return data.at(a) < 99; })) == 9); 40 | assert(search(data.size(), function([](int a) { return data.at(a) < 100; })) == 9); 41 | assert(search(data.size(), function([](int a) { return data.at(a) < 101; })) == 12); 42 | assert(search(data.size(), function([](int a) { return data.at(a) < 10000; })) == 13); 43 | assert(search(data.size(), function([](int a) { return data.at(a) < 10001; })) == 14); 44 | assert(search(7, function([](int a) { return data_desc.at(a) > 7; })) == 4); 45 | assert(search(1e9, function([](int a) { return 1e9 - a > 7; })) == 1e9 - 7); 46 | assert(search(2e9, function([](int a) { return true; })) == 2e9); // overflow test 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /test/disjoint-set/unionfind-Kattis-freckles.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | struct UnionFind { 10 | vector parent; 11 | vector rank; 12 | 13 | UnionFind(int size) { 14 | for (int i = 0; i < size; ++i) { 15 | parent.push_back(i); 16 | rank.push_back(0); 17 | } 18 | } 19 | 20 | int root(int i) { 21 | if (parent[i] != i) 22 | parent[i] = root(parent[i]); 23 | return parent[i]; 24 | } 25 | 26 | bool join(int i, int j) { 27 | int p = root(i), q = root(j); 28 | if (p == q) return false; 29 | if (rank[p] < rank[q]) { 30 | parent[p] = q; 31 | } else if (rank[p] > rank[q]) { 32 | parent[q] = p; 33 | } else { 34 | parent[q] = p; 35 | rank[q]++; 36 | } 37 | return true; 38 | } 39 | 40 | bool same(int i, int j) { 41 | return root(i) == root(j); 42 | } 43 | }; 44 | 45 | struct Node { 46 | double x, y; 47 | Node(double a, double b) {x = a; y = b;} 48 | double dist(Node& other) 49 | {return sqrt((x-other.x)*(x-other.x) + (y-other.y)*(y-other.y));} 50 | }; 51 | 52 | struct Edge { 53 | int from, to; 54 | double weight; 55 | Edge(int a, int b, double c=double()) { 56 | from = a; to = b; weight = c; 57 | } 58 | }; 59 | 60 | struct EdgeCmp { 61 | bool operator()(Edge& e1, Edge& e2) { 62 | return e1.weight > e2.weight; 63 | } 64 | }; 65 | 66 | vector mst(vector& edges, int numNodes) { 67 | priority_queue, EdgeCmp> q(edges.begin(), edges.end()); 68 | UnionFind u(numNodes); 69 | vector ret; 70 | 71 | while (!q.empty()) { 72 | Edge e = q.top(); q.pop(); 73 | if (u.join(e.to, e.from)) { 74 | ret.push_back(e); 75 | if ((int) ret.size() == numNodes - 1) return ret; 76 | } 77 | } 78 | return ret; 79 | } 80 | 81 | int main() { 82 | ios::sync_with_stdio(false); 83 | cout << fixed << setprecision(2); 84 | int TC; cin >> TC; 85 | while (TC--) { 86 | int n; cin >> n; 87 | 88 | vector nodes; 89 | for (int i = 0; i < n; ++i) { 90 | double a, b; cin >> a >> b; 91 | nodes.push_back(Node(a, b)); 92 | } 93 | 94 | vector edges; 95 | for (int i = 0; i < n; ++i) { 96 | for (int j = i+1; j < n; ++j) { 97 | double d = nodes[i].dist(nodes[j]); 98 | edges.push_back(Edge(i, j, d)); 99 | } 100 | } 101 | vector myMst = mst(edges, n); 102 | double sum = accumulate(myMst.begin(), myMst.end(), 0.0, 103 | [](double a, Edge& now){ return a + now.weight; }); 104 | cout << sum << "\n\n"; 105 | } 106 | } 107 | 108 | -------------------------------------------------------------------------------- /code/geometry/collinearpoints.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | const double EPS = 0.000000001; 8 | const double TAU = 6.28318530717958647692528; 9 | const double PI = TAU/2.0; 10 | using T = double; 11 | 12 | struct Point { 13 | T x, y; 14 | Point() {} 15 | Point(T a, T b) {x = a; y = b;} 16 | Point operator+(const Point& rhs) const {return Point(x+rhs.x, y+rhs.y);} 17 | Point operator-(const Point& rhs) const {return Point(x-rhs.x, y-rhs.y);} 18 | Point operator*(T scalar) const {return Point(x*scalar, y*scalar);} 19 | Point operator/(T scalar) const {return Point(x/scalar, y/scalar);} 20 | T dot(const Point& other) const {return x * other.x + y * other.y;} 21 | double len() const {return sqrt(x * x + y * y);} 22 | // Length squared 23 | T len2() const {return x*x + y*y;} 24 | double angle() const { return atan2(y, x); } 25 | double angle(const Point& other) const {return (other - *this).angle();} 26 | double dist(const Point& other) const {return (other - *this).len();} 27 | T cross(const Point& other) const {return x * other.y - other.x * y;} 28 | Point unit() const { return *this / len(); } 29 | Point rotate(double rad) const { return Point(cos(rad)*x-y*sin(rad), x*sin(rad)+y*cos(rad)); } 30 | Point norm() const {return Point(-y, x).unit();} 31 | }; 32 | using Vector = Point; 33 | 34 | vector compute_angles(vector& pts, int pivot) { 35 | vector angles; 36 | for (int i = 0; i < (int) pts.size(); ++i) { 37 | if (i != pivot) angles.push_back(pts[pivot].angle(pts[i])); 38 | } 39 | sort(angles.begin(), angles.end()); 40 | return angles; 41 | } 42 | 43 | int collinear_points(vector& pts) { 44 | if ((int) pts.size() == 1) return 1; 45 | 46 | int found_points = 0; 47 | for (int pivot = 0; pivot < (int) pts.size(); ++pivot) { 48 | vector angles = compute_angles(pts, pivot); 49 | int best_streak = 1; 50 | int streak = 1; 51 | 52 | double last_angle = angles[0]; 53 | for (int i = 1; i < (int) angles.size(); ++i) { 54 | double d = angles[i]; 55 | if (abs(last_angle - d) < EPS) { 56 | streak++; 57 | best_streak = best_streak > streak ? best_streak : streak; 58 | } else { 59 | streak = 1; 60 | last_angle = d; 61 | } 62 | } 63 | best_streak++; 64 | found_points = best_streak > found_points ? best_streak : found_points; 65 | } 66 | return found_points; 67 | } 68 | -------------------------------------------------------------------------------- /test/geometry/collinearpoints.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | const double EPS = 0.000000001; 8 | const double TAU = 6.28318530717958647692528; 9 | const double PI = TAU/2.0; 10 | using T = double; 11 | 12 | struct Point { 13 | T x, y; 14 | Point() {} 15 | Point(T a, T b) {x = a; y = b;} 16 | Point operator+(const Point& rhs) const {return Point(x+rhs.x, y+rhs.y);} 17 | Point operator-(const Point& rhs) const {return Point(x-rhs.x, y-rhs.y);} 18 | Point operator*(T scalar) const {return Point(x*scalar, y*scalar);} 19 | Point operator/(T scalar) const {return Point(x/scalar, y/scalar);} 20 | T dot(const Point& other) const {return x * other.x + y * other.y;} 21 | double len() const {return sqrt(x * x + y * y);} 22 | // Length squared 23 | T len2() const {return x*x + y*y;} 24 | double angle() const { return atan2(y, x); } 25 | double angle(const Point& other) const {return (other - *this).angle();} 26 | double dist(const Point& other) const {return (other - *this).len();} 27 | T cross(const Point& other) const {return x * other.y - other.x * y;} 28 | Point unit() const { return *this / len(); } 29 | Point rotate(double rad) const { return Point(cos(rad)*x-y*sin(rad), x*sin(rad)+y*cos(rad)); } 30 | Point norm() const {return Point(-y, x).unit();} 31 | }; 32 | using Vector = Point; 33 | 34 | vector compute_angles(vector& pts, int pivot) { 35 | vector angles; 36 | for (int i = 0; i < (int) pts.size(); ++i) { 37 | if (i != pivot) angles.push_back(pts[pivot].angle(pts[i])); 38 | } 39 | sort(angles.begin(), angles.end()); 40 | return angles; 41 | } 42 | 43 | int collinear_points(vector& pts) { 44 | if ((int) pts.size() == 1) return 1; 45 | 46 | int found_points = 0; 47 | for (int pivot = 0; pivot < (int) pts.size(); ++pivot) { 48 | vector angles = compute_angles(pts, pivot); 49 | int best_streak = 1; 50 | int streak = 1; 51 | 52 | double last_angle = angles[0]; 53 | for (int i = 1; i < (int) angles.size(); ++i) { 54 | double d = angles[i]; 55 | if (abs(last_angle - d) < EPS) { 56 | streak++; 57 | best_streak = best_streak > streak ? best_streak : streak; 58 | } else { 59 | streak = 1; 60 | last_angle = d; 61 | } 62 | } 63 | best_streak++; 64 | found_points = best_streak > found_points ? best_streak : found_points; 65 | } 66 | return found_points; 67 | } 68 | -------------------------------------------------------------------------------- /test/graphs/minspantree-Kattis-islandhopping.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * Interface 5 | */ 6 | class DisjointSet { 7 | public: 8 | DisjointSet(int size); 9 | 10 | void join(int a, int b); 11 | int findRoot(int i); 12 | bool sameSet(int a, int b); 13 | 14 | private: 15 | std::vector parent; 16 | std::vector rank; 17 | }; 18 | 19 | /** 20 | * Implementation 21 | */ 22 | DisjointSet::DisjointSet(int size) { 23 | parent = std::vector(size); 24 | rank = std::vector(size); 25 | for (int i = 0; i < size; ++i) { 26 | parent[i] = i; 27 | } 28 | } 29 | 30 | int DisjointSet::findRoot(int i) { 31 | return i != parent[i] ? (parent[i] = findRoot(parent[i])) : parent[i]; 32 | } 33 | 34 | void DisjointSet::join(int a, int b) { 35 | int i = findRoot(b), j = findRoot(a); 36 | if (i != j) { 37 | if (rank[i] > rank[j]) { 38 | parent[j] = i; 39 | } else { 40 | parent[i] = j; 41 | } 42 | if (rank[i] == rank[j]) rank[i]++; 43 | } 44 | } 45 | 46 | inline bool DisjointSet::sameSet(int a, int b) { 47 | return findRoot(a) == findRoot(b); 48 | } 49 | 50 | using namespace std; 51 | 52 | struct Point { 53 | double x, y; 54 | double dist(const Point& o) { 55 | return sqrt((o.x - x)*(o.x - x) + (o.y - y)*(o.y - y)); 56 | } 57 | }; 58 | 59 | struct Edge { 60 | int u, v; 61 | double w; 62 | }; 63 | 64 | bool edge_compare(const Edge& lhs, const Edge& rhs) { 65 | return lhs.w < rhs.w; 66 | } 67 | 68 | void solve(vector& edges, int nodes) { 69 | sort(edges.begin(), edges.end(), edge_compare); 70 | vector tree; 71 | DisjointSet ds(nodes); 72 | double sum = 0.0; 73 | for (Edge e : edges) { 74 | if (!ds.sameSet(e.u, e.v)) { 75 | ds.join(e.u, e.v); 76 | tree.push_back(e); 77 | sum += e.w; 78 | } else if (tree.size() == nodes - 1) { 79 | break; 80 | } 81 | } 82 | cout << sum << endl; 83 | } 84 | 85 | int main() { 86 | ios::sync_with_stdio(false); 87 | int n, islands; 88 | cout << fixed << setprecision(6); 89 | cin >> n; 90 | while (n--) { 91 | cin >> islands; 92 | vector isl(islands); 93 | for (Point& p : isl) 94 | cin >> p.x >> p.y; 95 | vector edges; 96 | for (int i = 0; i < islands; ++i) { 97 | for (int k = i+1; k < islands; ++k) { 98 | edges.push_back(Edge{i, k, isl[i].dist(isl[k])}); 99 | } 100 | } 101 | solve(edges, islands); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /test/LIS/LIS-Kattis-princeandprincess.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | using vi=vector; 4 | 5 | int binary_search(const vi& seq, const vi& best, 6 | int low, int high, int target) { 7 | auto holds = [&](int a) { 8 | return seq[best[a]] < target; 9 | }; 10 | 11 | for (int middle = (low+high)/2; high - low > 1; middle=(low+high)/2) 12 | holds(middle) ? low = middle : high = middle - 1; 13 | 14 | if (holds(high)) return high; 15 | else if (holds(low)) return low; 16 | else return 0; // Nothing is smaller than this (to the left) 17 | } 18 | 19 | 20 | // Returns the parent vector and the index to the last element in the 21 | // longest sequence. 22 | tuple longest_increasing_subsequence(const vi& seq) { 23 | int best_length = 1; 24 | vi current_best(seq.size() + 1); 25 | current_best[1] = 0; 26 | vi parent(seq.size()); 27 | for (int i = 0; i < seq.size(); ++i) parent[i] = i; 28 | 29 | // For every number except the first one, find The maximum j such 30 | // that j < i && seq[j] < seq[i]. We do this by binary searching 31 | // over the length of the "previous" LIS. We keep a tab on where 32 | // each longest subsequence is by using the "current_best" vector. 33 | 34 | for (int i = 1; i < seq.size(); ++i) { 35 | int len = binary_search(seq, current_best, 1, best_length, seq[i]); 36 | 37 | if (len == 0) { 38 | parent[i] = i; 39 | } else { 40 | parent[i] = current_best[len]; 41 | } 42 | 43 | const int len_with_this = len + 1; 44 | 45 | if (len_with_this > best_length || 46 | seq[i] < seq[current_best[len_with_this]]) { 47 | current_best[len_with_this] = i; 48 | best_length = max(len_with_this, best_length); 49 | } 50 | } 51 | 52 | return tuple(parent, current_best[best_length]); 53 | } 54 | 55 | int find_len(const vi& seq, int p) { 56 | return seq[p] == p ? 1 : 1 + find_len(seq, seq[p]); 57 | } 58 | 59 | int solve(int n, int p, int q) { 60 | // Rename the prince path to 1, 2, 3, 4 and so on 61 | // Take this naming and apply it to the princess 62 | // Find the longest increasing subsequence of this path, 63 | // the length of this path is optimal (solvable in O(N log N)) 64 | 65 | vi prince(p+1); 66 | vi princess(q+1); 67 | for_each(prince.begin(), prince.end(), [](int& i){cin >> i;}); 68 | for_each(princess.begin(), princess.end(), [](int& i){cin >> i;}); 69 | vi actual_princess; 70 | map renamed; 71 | int cnt = 0; 72 | for_each(prince.begin(), prince.end(), [&](int i){ 73 | renamed[i] = ++cnt; 74 | }); 75 | for_each(princess.begin(), princess.end(), [&](int i){ 76 | if (renamed.find(i) != renamed.end()) 77 | actual_princess.push_back(renamed[i]); 78 | }); 79 | auto solution = longest_increasing_subsequence(actual_princess); 80 | return find_len(get<0>(solution), get<1>(solution)); 81 | } 82 | 83 | int main() { 84 | ios::sync_with_stdio(false); 85 | int T, n, p, q; cin >> T; 86 | for (int k = 1; k <= T; ++k){ 87 | cin >> n >> p >> q; 88 | cout << "Case " << k << ": " << solve(n, p, q) << endl; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /code/segmenttree/segmenttree-2d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | using Int = int; 6 | const int MAXN = 505; 7 | Int Map[MAXN][MAXN]; 8 | int N; 9 | 10 | using MaxMin = pair; 11 | 12 | struct Node { 13 | int x, y; 14 | Int min_value, max_value; 15 | bool undef; 16 | 17 | Node() {} 18 | Node(int a, int b, int val, bool undef=false) { 19 | if (!undef) 20 | x = a; y = b; min_value = max_value = val; 21 | this -> undef = undef; 22 | } 23 | 24 | void revalue(const Node& other) { 25 | if (!other.undef) { 26 | if (undef) { 27 | min_value = other.min_value; 28 | max_value = other.max_value; 29 | undef = false; 30 | } else { 31 | min_value = min(min_value, other.min_value); 32 | max_value = max(max_value, other.max_value); 33 | } 34 | } 35 | } 36 | }; 37 | 38 | 39 | /* Implemented as a quadtree */ 40 | struct SegmentTree { 41 | Node nodes[2 * MAXN * MAXN]; 42 | 43 | SegmentTree() {} 44 | 45 | void build() {build(1, 1, 1, N, N);} 46 | 47 | Node build(int node, int a1, int b1, int a2, int b2, int level=0) { 48 | if (a1 > a2 or b1 > b2) 49 | return def(); 50 | 51 | if (a1 == a2 and b1 == b2) 52 | return nodes[node] = Node(a1, b1, Map[a1][b1]); 53 | 54 | nodes[node] = def(); 55 | nodes[node].revalue(build(4 * node - 2, a1, b1, (a1+a2)/2, (b1+b2)/2, level+1)); 56 | nodes[node].revalue(build(4 * node - 1, (a1+a2)/2+1, b1, a2, (b1+b2)/2, level+1)); 57 | nodes[node].revalue(build(4 * node + 0, (a1+a2)/2+1, (b1+b2)/2+1, a2, b2, level+1)); 58 | nodes[node].revalue(build(4 * node + 1, a1, (b1+b2)/2+1, (a1+a2)/2, b2, level+1)); 59 | return nodes[node]; 60 | } 61 | 62 | MaxMin query(int x1, int y1, int x2, int y2) { 63 | Node best = _query(1, 1, 1, N, N, x1, y1, x2, y2); 64 | return MaxMin(best.max_value, best.min_value); 65 | } 66 | 67 | Node _query(int node, int a1, int b1, int a2, int b2, int x1, int y1, int x2, int y2, int level=0, char c='a') { 68 | if (x1 > a2 or y1 > b2 or x2 < a1 or y2 < b1 or a1 > a2 or b1 > b2) 69 | return def(); 70 | 71 | if (x1 <= a1 and y1 <= b1 and a2 <= x2 and b2 <= y2) 72 | return nodes[node]; 73 | 74 | Node ret = def(); 75 | ret.revalue(_query(4 * node - 2, a1, b1, (a1+a2)/2, (b1+b2)/2, x1, y1, x2, y2, level+1, 'a')); 76 | ret.revalue(_query(4 * node - 1, (a1+a2)/2+1, b1, a2, (b1+b2)/2, x1, y1, x2, y2, level+1, 'b')); 77 | ret.revalue(_query(4 * node + 0, (a1+a2)/2+1, (b1+b2)/2+1, a2, b2, x1, y1, x2, y2, level+1, 'c')); 78 | ret.revalue(_query(4 * node + 1, a1, (b1+b2)/2+1, (a1+a2)/2, b2, x1, y1, x2, y2, level+1, 'd')); 79 | return ret; 80 | } 81 | 82 | void update(int x, int y, int c) { 83 | _update(1, 1, 1, N, N, x, y, c); 84 | } 85 | 86 | Node _update(int node, int a1, int b1, int a2, int b2, int x, int y, int val, int level=0) { 87 | if (a1 > a2 or b1 > b2) 88 | return def(); 89 | 90 | if (x > a2 or y > b2 or x < a1 or y < b1) 91 | return nodes[node]; 92 | 93 | if (x == a1 and y == b1 and x == a2 and y == b2) 94 | return nodes[node] = Node(x, y, val); 95 | 96 | Node ret = def(); 97 | ret.revalue(_update(4 * node - 2, a1, b1, (a1+a2)/2, (b1+b2)/2, x, y, val, level+1)); 98 | ret.revalue(_update(4 * node - 1, (a1+a2)/2+1, b1, a2, (b1+b2)/2, x, y, val, level+1)); 99 | ret.revalue(_update(4 * node + 0, (a1+a2)/2+1, (b1+b2)/2+1, a2, b2, x, y, val, level+1)); 100 | ret.revalue(_update(4 * node + 1, a1, (b1+b2)/2+1, (a1+a2)/2, b2, x, y, val, level+1)); 101 | return nodes[node] = ret; 102 | } 103 | 104 | Node def() { return Node(0, 0, 0, true); } 105 | 106 | }; 107 | -------------------------------------------------------------------------------- /test/graphs/maxflow-Kattis-maxflow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | using ValueT = long long; 5 | const ValueT INF = 1<<29; 6 | 7 | struct Edge { 8 | int from, to; 9 | ValueT weight; 10 | Edge(int a, int b, ValueT c) {from=a; to=b; weight=c;} 11 | }; 12 | 13 | struct Node { 14 | ValueT dist; 15 | int idx; 16 | bool visited; 17 | Node() {dist=INF; idx=-1; visited=false;} 18 | Node(int i) {dist=INF; idx=i; visited=false;} 19 | }; 20 | using T = long long; 21 | using vi=vector< int >; 22 | using vvi=vector< vi >; 23 | 24 | /** It is important to create the adjecency list with bidirectional edges */ 25 | 26 | const int UNDEF = -1; 27 | 28 | int SINK = UNDEF; 29 | int SOURCE = UNDEF; 30 | 31 | bool has_aug_path(vvi& flow_graph, vvi& adjacency_list, vi& parent) { 32 | vvi& adj = adjacency_list; 33 | 34 | int s = SOURCE, t = SINK; 35 | vector visited(flow_graph.size(), false); 36 | queue q; 37 | q.push(s); 38 | parent[s] = UNDEF; 39 | visited[s] = true; 40 | 41 | while (!q.empty()) { 42 | int now = q.front(); q.pop(); 43 | 44 | for (int neighbour : adj[now]) { 45 | const int n = neighbour; 46 | if (!visited[n] && flow_graph[now][n] > 0) { 47 | parent[n] = now; 48 | visited[n] = true; 49 | q.push(n); 50 | if (n == t) { 51 | return true; 52 | } 53 | } 54 | } 55 | } 56 | 57 | return false; 58 | } 59 | 60 | vvi added_flow; 61 | 62 | // Flow graph == Residual graph with capacities applied 63 | int max_flow(vvi& flow_graph, vvi& adjacency_list, int source, int sink) { 64 | for (int i = 0; i < flow_graph.size(); ++i) { 65 | added_flow.push_back(vi()); 66 | for (int k = 0; k < flow_graph[i].size(); ++k) 67 | added_flow[i].push_back(0); 68 | } 69 | SOURCE = source; 70 | SINK = sink; 71 | vi parent(flow_graph.size()); 72 | 73 | int maximum = 0; 74 | while (has_aug_path(flow_graph, adjacency_list, parent)) { 75 | int flow = INF; 76 | 77 | // Search through path for limiting flow 78 | for (int current = SINK; current != SOURCE; current = parent[current]) { 79 | int p = parent[current]; 80 | flow = min(flow, flow_graph[p][current]); 81 | } 82 | 83 | // Fill path with limiting flow 84 | for (int current = SINK; current != SOURCE; current = parent[current]) { 85 | int p = parent[current]; 86 | added_flow[p][current] += flow; 87 | added_flow[current][p] -= flow; 88 | flow_graph[p][current] -= flow; 89 | flow_graph[current][p] += flow; 90 | } 91 | 92 | maximum += flow; 93 | } 94 | 95 | return maximum; 96 | } 97 | 98 | 99 | int main() { 100 | ios::sync_with_stdio(false); 101 | int n, m, s, t; 102 | cin >> n >> m >> s >> t; 103 | vvi flow; 104 | vvi adj; 105 | for (int i = 0; i < n; ++i) { 106 | flow.push_back(vi()); 107 | for (int k = 0; k < n; ++k) { 108 | flow[i].push_back(0); 109 | } 110 | adj.push_back(vi()); 111 | } 112 | 113 | for (int i = 0; i < m; ++i) { 114 | int u, v, c; 115 | cin >> u >> v >> c; 116 | flow[u][v] = c; 117 | adj[u].push_back(v); 118 | adj[v].push_back(u); 119 | } 120 | int total_flow = max_flow(flow, adj, s, t); 121 | 122 | cout << n << " " << total_flow << " "; 123 | int num_edges = 0; 124 | vector > ans; 125 | for (int r = 0; r < n; ++r) { 126 | for (int c = 0; c < n; c++) { 127 | if (added_flow[r][c] > 0) { 128 | num_edges++; 129 | ans.push_back(tuple(r, c)); 130 | } 131 | } 132 | } 133 | cout << num_edges << endl; 134 | for (tuple t : ans) { 135 | int u = get<0>(t), v = get<1>(t); 136 | cout << u << " " << v << " " << added_flow[u][v] << endl; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /code/geometry/geometrylib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const double EPS = 0.0000001; 4 | const double TAU = 6.28318530717958647692528; 5 | const double PI = TAU/2.0; 6 | using T = int; 7 | /* 8 | template 9 | struct Point { 10 | typedef T coordType; 11 | typedef Point P; 12 | typedef const P & R; 13 | T x, y; 14 | explicit Point(T x=T(), T y=T()) : x( x), y( y) { } 15 | bool operator<(R p) const { return x 0 iff theta > pi 74 | 75 | double area(const Point& origin, const Point& p, const Point& q) { 76 | return (p - origin).cross(q - origin); 77 | } 78 | 79 | bool collinear(const Point& a, const Point& b, const Point& c) { 80 | return -EPS < area(b, a, c) && area(b, a, c) < EPS; 81 | } 82 | 83 | bool ccw(const Point& a, const Point& b, const Point& c) { 84 | return area(b, c, a) > EPS; 85 | } 86 | 87 | bool cw(const Point& a, const Point& b, const Point& c) { 88 | return area(b, c, a) < -EPS; 89 | } 90 | 91 | double triangleArea(const Point& origin, const Point& p, const Point& q) { 92 | return area(origin, p, q) / 2; 93 | } 94 | 95 | struct LineSegment { 96 | Point start, end; 97 | LineSegment(Point p1, Point p2) { 98 | start = p1; 99 | end = p2; 100 | } 101 | double len() const {return start.dist(end);} 102 | // Length Squared 103 | T len2() const {return (end - start).len2();} 104 | Point closestPoint(const Point& other) const { 105 | if ((end - start).dot(other - end) > 0) return end; 106 | if ((start - end).dot(other - start) > 0) return start; 107 | double t = (other - start).dot(end - start) / len2(); 108 | return start + (end - start).scale(t); 109 | } 110 | }; 111 | 112 | struct Circle { 113 | Point middle; 114 | double radius; 115 | Circle(Point p, double r) {middle = p; radius = r;} 116 | bool overlaps(const Circle& other) const { 117 | return other.radius + radius > middle.dist(other.middle); 118 | } 119 | double area() const { return PI * radius * radius; } 120 | }; 121 | -------------------------------------------------------------------------------- /latexme.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import sys 3 | import os 4 | from collections import namedtuple, defaultdict 5 | 6 | CODE_DIR = 'code' 7 | 8 | Sections = defaultdict(lambda : 'Other', 9 | { 10 | 'graphs' : 'Graph', 11 | 'binary-search' : 'Binary Search', 12 | 'disjoint-set' : 'Disjoint Set', 13 | 'c++11' : 'C++11 Features', 14 | 'fenwick' : 'Fenwick', 15 | 'geometry' : 'Geometry', 16 | 'math' : 'Math', 17 | 'string' : 'String', 18 | }) 19 | 20 | FileTypes = { 21 | 'cpp' : 'C++', 22 | 'md' : 'Markdown', 23 | 'java' : 'Java', 24 | 'py' : 'Python', 25 | } 26 | 27 | def is_code(code): 28 | return code.filetype in 'C++', 'Java', 'Python' 29 | 30 | def latexify(text): 31 | return text.replace('_', r'\_').replace('[', r'\lbrack ').replace( 32 | ']', r'\rbrack ') 33 | 34 | Entry = namedtuple('Entry', ['filename', 'text', 'filetype', 35 | 'section', 'path']) 36 | 37 | def append(collection, item): 38 | collection.append(item) 39 | 40 | def recursive_collect(collection, directory): 41 | for fname in os.listdir(directory): 42 | path = os.path.join(directory, fname) 43 | if os.path.isdir(path): 44 | if not path.endswith('test'): 45 | recursive_collect(collection, path) 46 | 47 | elif os.path.isfile(path): 48 | with open(path, 'r') as f: 49 | content = [latexify(line) for line in f.readlines()] 50 | 51 | def first_match(dictionary, string): 52 | for key in dictionary: 53 | if string.endswith(key): 54 | return dictionary[key] 55 | return None 56 | 57 | filetype = first_match(FileTypes, fname) 58 | section = first_match(Sections, directory) 59 | if filetype and section: 60 | append(collection, Entry( 61 | latexify(fname), content, latexify(filetype), 62 | latexify(section), path)) 63 | 64 | 65 | header = r"""\title{A Competitive Programming Cheat Sheet} 66 | 67 | \documentclass[11pt,twocolumn,landscape]{article} 68 | 69 | \usepackage{listings} 70 | \usepackage[landscape,margin=0.5in]{geometry} 71 | \usepackage[usenames,dvipsnames]{color} 72 | \usepackage[utf8]{inputenc} 73 | \author{23.15\% Mer Kräm} 74 | 75 | \definecolor{comment-color}{rgb}{0.0,0.3,0.0} % Comment color 76 | \definecolor{highlight}{RGB}{255,251,204} % Code highlight color 77 | \definecolor{light-gray}{gray}{0.85} 78 | \definecolor{background-color}{gray}{0.95} 79 | \definecolor{string-color}{rgb}{0.05,0.6,0.0} 80 | \definecolor{keyword-color}{RGB}{255,41,41} 81 | 82 | \lstset{ 83 | language=C++, 84 | basicstyle=\footnotesize, 85 | backgroundcolor=\color{background-color}, 86 | commentstyle=\color{comment-color}, 87 | stringstyle=\color{string-color}, 88 | keywordstyle=\color{keyword-color}, 89 | } 90 | \begin{document} 91 | \maketitle 92 | \clearpage 93 | 94 | """ 95 | 96 | if __name__ == '__main__': 97 | if len(sys.argv) != 2: 98 | print("'python3 latexme.py output_filename' needs to be run") 99 | exit(1) 100 | entries = [] 101 | recursive_collect(entries, CODE_DIR) 102 | entries.sort(key=lambda x: x.section or "ZZZ") 103 | last_section = "TheCoolestPlaceholderAlive" 104 | sections = "" 105 | for entry in entries: 106 | if entry.section != last_section: 107 | #sections += r"\clearpage" + "\n" 108 | sections += r"\section{" + entry.section + "}\n\n" 109 | if is_code(entry): 110 | sections += r'\subsection{' + entry.filename + '}\n' 111 | sections += r'\lstinputlisting{"' + entry.path + '"}\n\n' 112 | 113 | last_section = entry.section 114 | sections += r"\end{document}" + "\n" 115 | full_text = header + sections 116 | with open(sys.argv[1], 'w') as f: 117 | print(full_text, file=f) 118 | 119 | 120 | -------------------------------------------------------------------------------- /test/graphs/maxflow-Kattis-elementarymath.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | using T = long long; 4 | using vi=vector< int >; 5 | using vvi=vector< vi >; 6 | 7 | /** It is important to create the adjecency list with bidirectional edges*/ 8 | 9 | const int INF = 100000; 10 | const int UNDEF = -1; 11 | 12 | int SINK = UNDEF; 13 | int SOURCE = UNDEF; 14 | 15 | bool has_aug_path(vvi& flow_graph, vvi& adjacency_list, vi& parent) { 16 | vvi& adj = adjacency_list; 17 | 18 | int s = SOURCE, t = SINK; 19 | vector visited(flow_graph.size(), false); 20 | queue q; 21 | q.push(s); 22 | parent[s] = UNDEF; 23 | visited[s] = true; 24 | 25 | while (!q.empty()) { 26 | int now = q.front(); q.pop(); 27 | 28 | for (int neighbour : adj[now]) { 29 | const int n = neighbour; 30 | if (!visited[n] && flow_graph[now][n] > 0) { 31 | parent[n] = now; 32 | visited[n] = true; 33 | q.push(n); 34 | if (n == t) { 35 | return true; 36 | } 37 | } 38 | } 39 | } 40 | 41 | return false; 42 | } 43 | 44 | // Flow graph == Residual graph with capacities applied 45 | int max_flow(vvi& flow_graph, vvi& adjacency_list, int source, int sink) { 46 | SOURCE = source; 47 | SINK = sink; 48 | vi parent(flow_graph.size()); 49 | 50 | int maximum = 0; 51 | while (has_aug_path(flow_graph, adjacency_list, parent)) { 52 | int flow = INF; 53 | 54 | // Search through path for limiting flow 55 | for (int current = SINK; current != SOURCE; current = parent[current]) { 56 | int p = parent[current]; 57 | flow = min(flow, flow_graph[p][current]); 58 | } 59 | 60 | // Fill path with limiting flow 61 | for (int current = SINK; current != SOURCE; current = parent[current]) { 62 | int p = parent[current]; 63 | flow_graph[p][current] -= flow; 64 | flow_graph[current][p] += flow; 65 | } 66 | 67 | maximum += flow; 68 | } 69 | 70 | return maximum; 71 | } 72 | 73 | namespace problem { 74 | 75 | void solve_kattis() { 76 | int n; cin >> n; 77 | vector l(n), r(n); 78 | vvi flow((4*n) + 2, vector((4*n) + 2)); 79 | vvi adj_list((4*n) + 2); 80 | 81 | int source = 4*n; 82 | int sink = 4*n + 1; 83 | 84 | map to_id; 85 | int id = n; 86 | auto add_to_graph = [&](T val) { 87 | if (to_id.find(val) == to_id.end()) 88 | to_id[val] = id++; 89 | }; 90 | 91 | for (int i = 0; i < n; ++i) { 92 | cin >> l[i] >> r[i]; 93 | T add = l[i] + r[i], sub = l[i] - r[i], mul = l[i] * r[i]; 94 | 95 | add_to_graph(add); 96 | add_to_graph(sub); 97 | add_to_graph(mul); 98 | 99 | flow[source][i] = 1; 100 | adj_list[source].push_back(i); 101 | adj_list[i].push_back(source); 102 | 103 | vector vals{to_id[add], to_id[sub], to_id[mul]}; 104 | 105 | for (int v : vals) { 106 | adj_list[i].push_back(v); 107 | adj_list[v].push_back(i); 108 | adj_list[v].push_back(sink); 109 | adj_list[sink].push_back(v); 110 | flow[i][v] = 1, flow[v][sink] = 1; 111 | } 112 | } 113 | 114 | int maximum_flow = max_flow(flow, adj_list, source, sink); 115 | set rhs; 116 | 117 | for (int i = 0; i < n; ++i) { 118 | T add = l[i] + r[i], sub = l[i] - r[i], mul = l[i] * r[i]; 119 | int cnt = 0; 120 | if (flow[i][to_id[add]] == 0) rhs.insert(i), cnt++; 121 | if (flow[i][to_id[mul]] == 0) rhs.insert(i), cnt++; 122 | if (flow[i][to_id[sub]] == 0) rhs.insert(i), cnt++; 123 | } 124 | 125 | if (maximum_flow == n) { 126 | for (int i = 0; i < n; ++i) { 127 | T add = l[i] + r[i], sub = l[i] - r[i], mul = l[i] * r[i]; 128 | if (flow[to_id[add]][i] != 0) { 129 | cout << l[i] << " + " << r[i] << " = " << add << endl; 130 | } else if (flow[to_id[sub]][i] != 0) { 131 | cout << l[i] << " - " << r[i] << " = " << sub << endl; 132 | } else if (flow[to_id[mul]][i] != 0) { 133 | cout << l[i] << " * " << r[i] << " = " << mul << endl; 134 | } 135 | } 136 | } else { 137 | cout << "impossible" << endl; 138 | } 139 | } 140 | 141 | }; 142 | 143 | 144 | int main() { 145 | problem::solve_kattis(); 146 | } 147 | -------------------------------------------------------------------------------- /test/segmenttree/census-UVa11297.cpp: -------------------------------------------------------------------------------- 1 | /* Solves UVA 11297 using a 2D SegmentTree*/ 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | using Int = int; 9 | const int MAXN = 505; 10 | Int Map[MAXN][MAXN]; 11 | int N; 12 | 13 | void readMap() { 14 | for (int x = 1; x <= N; ++x) { 15 | for (int y = 1; y <= N; ++y){ 16 | cin >> Map[x][y]; 17 | } 18 | } 19 | } 20 | 21 | using MaxMin = pair; 22 | 23 | struct Node { 24 | int x, y; 25 | Int min_value, max_value; 26 | bool undef; 27 | 28 | Node() {} 29 | Node(int a, int b, int val, bool undef=false) { 30 | if (!undef) 31 | x = a; y = b; min_value = max_value = val; 32 | this -> undef = undef; 33 | } 34 | 35 | void revalue(const Node& other) { 36 | if (!other.undef) { 37 | if (undef) { 38 | min_value = other.min_value; 39 | max_value = other.max_value; 40 | undef = false; 41 | } else { 42 | min_value = min(min_value, other.min_value); 43 | max_value = max(max_value, other.max_value); 44 | } 45 | } 46 | } 47 | }; 48 | 49 | 50 | struct SegmentTree { 51 | Node nodes[2 * MAXN * MAXN]; 52 | 53 | SegmentTree() {} 54 | 55 | void build() { 56 | build(1, 1, 1, N, N); 57 | } 58 | 59 | Node build(int node, int a1, int b1, int a2, int b2, int level=0) { 60 | if (a1 > a2 or b1 > b2) 61 | return def(); 62 | 63 | if (a1 == a2 and b1 == b2) 64 | return nodes[node] = Node(a1, b1, Map[a1][b1]); 65 | 66 | nodes[node] = def(); 67 | nodes[node].revalue(build(4 * node - 2, a1, b1, (a1+a2)/2, (b1+b2)/2, level+1)); 68 | nodes[node].revalue(build(4 * node - 1, (a1+a2)/2+1, b1, a2, (b1+b2)/2, level+1)); 69 | nodes[node].revalue(build(4 * node + 0, (a1+a2)/2+1, (b1+b2)/2+1, a2, b2, level+1)); 70 | nodes[node].revalue(build(4 * node + 1, a1, (b1+b2)/2+1, (a1+a2)/2, b2, level+1)); 71 | return nodes[node]; 72 | } 73 | 74 | MaxMin query(int x1, int y1, int x2, int y2) { 75 | Node best = _query(1, 1, 1, N, N, x1, y1, x2, y2); 76 | return MaxMin(best.max_value, best.min_value); 77 | } 78 | 79 | Node _query(int node, int a1, int b1, int a2, int b2, int x1, int y1, int x2, int y2, int level=0, char c='a') { 80 | if (x1 > a2 or y1 > b2 or x2 < a1 or y2 < b1 or a1 > a2 or b1 > b2) 81 | return def(); 82 | 83 | if (x1 <= a1 and y1 <= b1 and a2 <= x2 and b2 <= y2) { 84 | return nodes[node]; 85 | } 86 | 87 | Node ret = def(); 88 | ret.revalue(_query(4 * node - 2, a1, b1, (a1+a2)/2, (b1+b2)/2, x1, y1, x2, y2, level+1, 'a')); 89 | ret.revalue(_query(4 * node - 1, (a1+a2)/2+1, b1, a2, (b1+b2)/2, x1, y1, x2, y2, level+1, 'b')); 90 | ret.revalue(_query(4 * node + 0, (a1+a2)/2+1, (b1+b2)/2+1, a2, b2, x1, y1, x2, y2, level+1, 'c')); 91 | ret.revalue(_query(4 * node + 1, a1, (b1+b2)/2+1, (a1+a2)/2, b2, x1, y1, x2, y2, level+1, 'd')); 92 | return ret; 93 | } 94 | 95 | void update(int x, int y, int c) { 96 | _update(1, 1, 1, N, N, x, y, c); 97 | } 98 | 99 | Node _update(int node, int a1, int b1, int a2, int b2, int x, int y, int val, int level=0) { 100 | if (a1 > a2 or b1 > b2) 101 | return def(); 102 | 103 | if (x > a2 or y > b2 or x < a1 or y < b1) 104 | return nodes[node]; 105 | 106 | if (x == a1 and y == b1 and x == a2 and y == b2) 107 | return nodes[node] = Node(x, y, val); 108 | 109 | Node ret = def(); 110 | ret.revalue(_update(4 * node - 2, a1, b1, (a1+a2)/2, (b1+b2)/2, x, y, val, level+1)); 111 | ret.revalue(_update(4 * node - 1, (a1+a2)/2+1, b1, a2, (b1+b2)/2, x, y, val, level+1)); 112 | ret.revalue(_update(4 * node + 0, (a1+a2)/2+1, (b1+b2)/2+1, a2, b2, x, y, val, level+1)); 113 | ret.revalue(_update(4 * node + 1, a1, (b1+b2)/2+1, (a1+a2)/2, b2, x, y, val, level+1)); 114 | return nodes[node] = ret; 115 | } 116 | 117 | Node def() { 118 | return Node(0, 0, 0, true); 119 | } 120 | 121 | }; 122 | 123 | 124 | SegmentTree st; 125 | int main() { 126 | cin >> N; 127 | readMap(); 128 | st.build(); 129 | 130 | int Q; cin >> Q; 131 | while (Q--) { 132 | char tmp; cin >> tmp; 133 | if (tmp == 'c') { 134 | int a, b, c; 135 | cin >> a >> b >> c; 136 | st.update(a, b, c); 137 | } else if (tmp == 'q') { 138 | int a, b, c, d; 139 | cin >> a >> b >> c >> d; 140 | MaxMin mm = st.query(a, b, c ,d); 141 | cout << mm.first << " " << mm.second << endl; 142 | } 143 | } 144 | } 145 | 146 | -------------------------------------------------------------------------------- /test/segmenttree/segmenttree-UVa11297.cpp: -------------------------------------------------------------------------------- 1 | /* Solves UVA 11297 using a 2D SegmentTree*/ 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | using Int = int; 9 | const int MAXN = 505; 10 | Int Map[MAXN][MAXN]; 11 | int N; 12 | 13 | void readMap() { 14 | for (int x = 1; x <= N; ++x) { 15 | for (int y = 1; y <= N; ++y){ 16 | cin >> Map[x][y]; 17 | } 18 | } 19 | } 20 | 21 | using MaxMin = pair; 22 | 23 | struct Node { 24 | int x, y; 25 | Int min_value, max_value; 26 | bool undef; 27 | 28 | Node() {} 29 | Node(int a, int b, int val, bool undef=false) { 30 | if (!undef) 31 | x = a; y = b; min_value = max_value = val; 32 | this -> undef = undef; 33 | } 34 | 35 | void revalue(const Node& other) { 36 | if (!other.undef) { 37 | if (undef) { 38 | min_value = other.min_value; 39 | max_value = other.max_value; 40 | undef = false; 41 | } else { 42 | min_value = min(min_value, other.min_value); 43 | max_value = max(max_value, other.max_value); 44 | } 45 | } 46 | } 47 | }; 48 | 49 | 50 | struct SegmentTree { 51 | Node nodes[2 * MAXN * MAXN]; 52 | 53 | SegmentTree() {} 54 | 55 | void build() { 56 | build(1, 1, 1, N, N); 57 | } 58 | 59 | Node build(int node, int a1, int b1, int a2, int b2, int level=0) { 60 | if (a1 > a2 or b1 > b2) 61 | return def(); 62 | 63 | if (a1 == a2 and b1 == b2) 64 | return nodes[node] = Node(a1, b1, Map[a1][b1]); 65 | 66 | nodes[node] = def(); 67 | nodes[node].revalue(build(4 * node - 2, a1, b1, (a1+a2)/2, (b1+b2)/2, level+1)); 68 | nodes[node].revalue(build(4 * node - 1, (a1+a2)/2+1, b1, a2, (b1+b2)/2, level+1)); 69 | nodes[node].revalue(build(4 * node + 0, (a1+a2)/2+1, (b1+b2)/2+1, a2, b2, level+1)); 70 | nodes[node].revalue(build(4 * node + 1, a1, (b1+b2)/2+1, (a1+a2)/2, b2, level+1)); 71 | return nodes[node]; 72 | } 73 | 74 | MaxMin query(int x1, int y1, int x2, int y2) { 75 | Node best = _query(1, 1, 1, N, N, x1, y1, x2, y2); 76 | return MaxMin(best.max_value, best.min_value); 77 | } 78 | 79 | Node _query(int node, int a1, int b1, int a2, int b2, int x1, int y1, int x2, int y2, int level=0, char c='a') { 80 | if (x1 > a2 or y1 > b2 or x2 < a1 or y2 < b1 or a1 > a2 or b1 > b2) 81 | return def(); 82 | 83 | if (x1 <= a1 and y1 <= b1 and a2 <= x2 and b2 <= y2) { 84 | return nodes[node]; 85 | } 86 | 87 | Node ret = def(); 88 | ret.revalue(_query(4 * node - 2, a1, b1, (a1+a2)/2, (b1+b2)/2, x1, y1, x2, y2, level+1, 'a')); 89 | ret.revalue(_query(4 * node - 1, (a1+a2)/2+1, b1, a2, (b1+b2)/2, x1, y1, x2, y2, level+1, 'b')); 90 | ret.revalue(_query(4 * node + 0, (a1+a2)/2+1, (b1+b2)/2+1, a2, b2, x1, y1, x2, y2, level+1, 'c')); 91 | ret.revalue(_query(4 * node + 1, a1, (b1+b2)/2+1, (a1+a2)/2, b2, x1, y1, x2, y2, level+1, 'd')); 92 | return ret; 93 | } 94 | 95 | void update(int x, int y, int c) { 96 | _update(1, 1, 1, N, N, x, y, c); 97 | } 98 | 99 | Node _update(int node, int a1, int b1, int a2, int b2, int x, int y, int val, int level=0) { 100 | if (a1 > a2 or b1 > b2) 101 | return def(); 102 | 103 | if (x > a2 or y > b2 or x < a1 or y < b1) 104 | return nodes[node]; 105 | 106 | if (x == a1 and y == b1 and x == a2 and y == b2) 107 | return nodes[node] = Node(x, y, val); 108 | 109 | Node ret = def(); 110 | ret.revalue(_update(4 * node - 2, a1, b1, (a1+a2)/2, (b1+b2)/2, x, y, val, level+1)); 111 | ret.revalue(_update(4 * node - 1, (a1+a2)/2+1, b1, a2, (b1+b2)/2, x, y, val, level+1)); 112 | ret.revalue(_update(4 * node + 0, (a1+a2)/2+1, (b1+b2)/2+1, a2, b2, x, y, val, level+1)); 113 | ret.revalue(_update(4 * node + 1, a1, (b1+b2)/2+1, (a1+a2)/2, b2, x, y, val, level+1)); 114 | return nodes[node] = ret; 115 | } 116 | 117 | Node def() { 118 | return Node(0, 0, 0, true); 119 | } 120 | 121 | }; 122 | 123 | 124 | SegmentTree st; 125 | int main() { 126 | cin >> N; 127 | readMap(); 128 | st.build(); 129 | 130 | int Q; cin >> Q; 131 | while (Q--) { 132 | char tmp; cin >> tmp; 133 | if (tmp == 'c') { 134 | int a, b, c; 135 | cin >> a >> b >> c; 136 | st.update(a, b, c); 137 | } else if (tmp == 'q') { 138 | int a, b, c, d; 139 | cin >> a >> b >> c >> d; 140 | MaxMin mm = st.query(a, b, c ,d); 141 | cout << mm.first << " " << mm.second << endl; 142 | } 143 | } 144 | } 145 | 146 | --------------------------------------------------------------------------------