├── snippets ├── cpp │ ├── shortcuts │ │ ├── vv.cpp │ │ ├── ssize.cpp │ │ ├── rint.cpp │ │ ├── lambda.cpp │ │ ├── print.cpp │ │ ├── reresize.cpp │ │ ├── rvar.cpp │ │ ├── forel.cpp │ │ ├── foru.cpp │ │ ├── 2pb.cpp │ │ ├── ford.cpp │ │ ├── infop.cpp │ │ ├── testsfor.cpp │ │ └── foriel.cpp │ ├── utility │ │ ├── islocal.cpp │ │ ├── sync_false.cpp │ │ ├── usaco.cpp │ │ ├── mainDefault_iostream.cpp │ │ ├── mainDefault.cpp │ │ ├── mainSimple.cpp │ │ ├── bincludes.cpp │ │ ├── string_utility.cpp │ │ ├── cout_anything.cpp │ │ └── includes.cpp │ ├── definitions │ │ ├── def_types.cpp │ │ └── def_consts.cpp │ ├── io │ │ ├── read │ │ │ ├── read_flow.cpp │ │ │ ├── read_graph.cpp │ │ │ ├── read_graph_pondere.cpp │ │ │ ├── read_max_matching.cpp │ │ │ └── read_min_cost_flow.cpp │ │ └── convertion │ │ │ ├── grid_to_graph.cpp │ │ │ └── grid_to_flow.cpp │ ├── contest_scpecific │ │ ├── codejam_main.cpp │ │ └── battleDev_main.cpp │ ├── algo │ │ ├── general │ │ │ ├── algo_dicho.cpp │ │ │ ├── algo_union_find.cpp │ │ │ └── algo_merge_sort.cpp │ │ ├── graphs │ │ │ ├── shortest_path │ │ │ │ ├── algo_remonte_dijkstra.cpp │ │ │ │ ├── algo_remonte_bfs.cpp │ │ │ │ ├── algo_bfs.cpp │ │ │ │ ├── algo_bellman_ford.cpp │ │ │ │ ├── algo_dijkstra.cpp │ │ │ │ └── algo_floyd_warshall.cpp │ │ │ ├── algo_dfs.cpp │ │ │ ├── algo_contain_cycle.cpp │ │ │ ├── flow_max_matching │ │ │ │ ├── algo_min_cut.cpp │ │ │ │ ├── algo_min_cut_sparse.cpp │ │ │ │ ├── algo_max_matching.cpp │ │ │ │ ├── algo_flow.cpp │ │ │ │ ├── algo_flow_sparse.cpp │ │ │ │ ├── algo_min_cost_max_flow_sparse.cpp │ │ │ │ ├── algo_min_cost_max_flow.cpp │ │ │ │ ├── algo_min_cost_max_flow_negative.cpp │ │ │ │ └── algo_min_cost_max_flow_slower.cpp │ │ │ └── algo_tri_topo.cpp │ │ ├── geometry │ │ │ ├── geo_rects.cpp │ │ │ ├── geo_shapes.cpp │ │ │ ├── geo_convex_hull.cpp │ │ │ ├── geo_segs.cpp │ │ │ └── geo_base.cpp │ │ └── maths │ │ │ ├── math_usual.cpp │ │ │ └── math_primes.cpp │ ├── structs │ │ ├── str_graph.cpp │ │ ├── str_segtree.cpp │ │ ├── str_grid.cpp │ │ ├── segtrees │ │ │ ├── segtree_template.cpp │ │ │ ├── segtree_sum.cpp │ │ │ ├── segtree_template_old.cpp │ │ │ └── segtree_max.cpp │ │ ├── str_pos.cpp │ │ ├── str_carttree.cpp │ │ └── str_bigint.cpp │ └── tools │ │ └── tool_reindexer.cpp └── python │ ├── short │ ├── forr.py │ ├── cin.py │ ├── fprint.py │ ├── rint.py │ ├── rr.py │ ├── cout.py │ ├── foru.py │ ├── rmint.py │ ├── ford.py │ ├── lrmint.py │ ├── read_print.py │ └── struct.py │ ├── algo │ ├── general │ │ ├── algo_dynamique.py │ │ ├── algo_cumul.py │ │ ├── algo_dicho.py │ │ ├── algo_union_find.py │ │ └── algo_merge_sort.py │ ├── graphs │ │ ├── algo_dfs.py │ │ ├── algo_floyd_warshall.py │ │ ├── algo_bellman_ford.py │ │ ├── algo_dij.py │ │ ├── algo_cfc.py │ │ └── algo_bfs.py │ ├── flows │ │ ├── algo_min_cut.py │ │ ├── algo_max_flow.py │ │ ├── algo_max_matching.py │ │ └── algo_min_cost_max_flow.py │ └── convex_hull.py │ ├── main │ ├── mainMini.py │ └── main.py │ ├── util │ ├── util_combi.py │ ├── util_sequences_str.py │ ├── util_search.py │ ├── util_collections.py │ ├── util_math.py │ └── util_points_geo.py │ ├── structs │ ├── str_graph.py │ ├── str_heap.py │ ├── str_deque.py │ ├── str_segtree_sum.py │ ├── str_segtree_max.py │ ├── str_cartesian_tree.py │ └── str_segtree.py │ └── extras │ └── str_cartesian_tree_extras.py ├── .gitignore ├── genAll.sh ├── scripts ├── templates │ └── sublimeSnippet ├── mvCodeSnippets.sh ├── genSubTextSnippets.py ├── genVSCodeSnippets.py ├── genDoc.py └── utils.py ├── README.md └── snippets.md /snippets/cpp/shortcuts/vv.cpp: -------------------------------------------------------------------------------- 1 | vector<${1:int}> $0 -------------------------------------------------------------------------------- /snippets/python/short/forr.py: -------------------------------------------------------------------------------- 1 | for ${1:_} in range($2) -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/ssize.cpp: -------------------------------------------------------------------------------- 1 | (int)${1:vect}.size()$0 -------------------------------------------------------------------------------- /snippets/python/short/cin.py: -------------------------------------------------------------------------------- 1 | sys.stdin.readline().rstrip() -------------------------------------------------------------------------------- /snippets/python/short/fprint.py: -------------------------------------------------------------------------------- 1 | sys.stdin.write(f"{$0}\n") -------------------------------------------------------------------------------- /snippets/python/short/rint.py: -------------------------------------------------------------------------------- 1 | int(sys.stdin.readline()) -------------------------------------------------------------------------------- /snippets/python/short/rr.py: -------------------------------------------------------------------------------- 1 | sys.stdin.readline().rstrip() -------------------------------------------------------------------------------- /snippets/python/short/cout.py: -------------------------------------------------------------------------------- 1 | sys.stdout.write(f'{$1}\n') 2 | $0 -------------------------------------------------------------------------------- /snippets/python/short/foru.py: -------------------------------------------------------------------------------- 1 | for ${1:i} in range(${2:n}): 2 | $0 -------------------------------------------------------------------------------- /snippets/python/short/rmint.py: -------------------------------------------------------------------------------- 1 | map(int, sys.stdin.readline().split()) -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/rint.cpp: -------------------------------------------------------------------------------- 1 | int ${1:n}; 2 | cin >> ${1/,/ >>/g}; 3 | $0 -------------------------------------------------------------------------------- /snippets/python/short/ford.py: -------------------------------------------------------------------------------- 1 | for ${1:i} in range(${2:n}-1, -1, -1): 2 | $0 -------------------------------------------------------------------------------- /snippets/python/short/lrmint.py: -------------------------------------------------------------------------------- 1 | list(map(int, sys.stdin.readline().split())) -------------------------------------------------------------------------------- /snippets/cpp/utility/islocal.cpp: -------------------------------------------------------------------------------- 1 | #ifdef on_local 2 | $0 3 | #else 4 | #endif 5 | -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/lambda.cpp: -------------------------------------------------------------------------------- 1 | [&](${2:const ${1:int}& a, const $1& b}){ 2 | $0 3 | } -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/print.cpp: -------------------------------------------------------------------------------- 1 | cout << ${1/ / << " " << /g} << "${2:\n}"; // $1 2 | $0 -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/reresize.cpp: -------------------------------------------------------------------------------- 1 | ${1:vect}.resize(0); ${1:vect}.resize(${2:n}); 2 | $0 -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/rvar.cpp: -------------------------------------------------------------------------------- 1 | ${1:string} ${2:var}; 2 | cin >> ${2/,/ >>/g}; 3 | $0 -------------------------------------------------------------------------------- /snippets/python/short/read_print.py: -------------------------------------------------------------------------------- 1 | import sys 2 | print("".join(sys.stdin.readlines())) -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/forel.cpp: -------------------------------------------------------------------------------- 1 | for (auto& ${1:element} : ${2:vectorName}) { 2 | $0 3 | } -------------------------------------------------------------------------------- /snippets/python/short/struct.py: -------------------------------------------------------------------------------- 1 | ${1:StructName} = namedtuple('$1', ['${2:params}']) 2 | $0 -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/foru.cpp: -------------------------------------------------------------------------------- 1 | for (int i${1:Vache} = 0; i$1 < ${2:nb$1s}; i$1++) { 2 | $0 3 | } -------------------------------------------------------------------------------- /snippets/python/algo/general/algo_dynamique.py: -------------------------------------------------------------------------------- 1 | @cache 2 | def compute(args): 3 | pass # -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/2pb.cpp: -------------------------------------------------------------------------------- 1 | ${1:vect}[${2:a}].push_back(${3:b}); 2 | $1[$3].push_back($2); 3 | $0 -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/ford.cpp: -------------------------------------------------------------------------------- 1 | for (int i${1:Vache} = ${2:nb$1s-1}; i$1 >= 0; i$1--) { 2 | $0 3 | } -------------------------------------------------------------------------------- /snippets/cpp/utility/sync_false.cpp: -------------------------------------------------------------------------------- 1 | ios::sync_with_stdio(false); 2 | cout.tie(0); cin.tie(0); 3 | 4 | 5 | -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/infop.cpp: -------------------------------------------------------------------------------- 1 | bool operator < (const ${1:Str}& a, const ${1}& b) { 2 | return $0; 3 | } 4 | -------------------------------------------------------------------------------- /snippets/cpp/utility/usaco.cpp: -------------------------------------------------------------------------------- 1 | freopen("$1.in", "r", stdin); 2 | freopen("$1.out", "w", stdout); 3 | 4 | $0 5 | -------------------------------------------------------------------------------- /snippets/cpp/definitions/def_types.cpp: -------------------------------------------------------------------------------- 1 | using lli = long long int; 2 | using ulli = unsigned long long int; 3 | 4 | 5 | -------------------------------------------------------------------------------- /snippets/cpp/utility/mainDefault_iostream.cpp: -------------------------------------------------------------------------------- 1 | signed main() { 2 | std::ios_base::sync_with_stdio(false); 3 | 4 | $0 5 | } 6 | -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/testsfor.cpp: -------------------------------------------------------------------------------- 1 | int nbTests; 2 | cin >> nbTests; 3 | for (int iTest = 0; iTest < nbTests; iTest++) { 4 | $0 5 | } -------------------------------------------------------------------------------- /snippets/cpp/shortcuts/foriel.cpp: -------------------------------------------------------------------------------- 1 | for (int ${1:i} = 0; $1 < (int)$3.size(); $1++) { 2 | auto& ${2:el} = ${3:vectorName}[$1]; 3 | $0 4 | } -------------------------------------------------------------------------------- /snippets/python/algo/general/algo_cumul.py: -------------------------------------------------------------------------------- 1 | def cumul(l, inplace=False): 2 | if not inplace: l = l[:] 3 | for i in range(1, len(l)): l[i] += l[i-1] 4 | return l 5 | 6 | $0 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Pretty JSON/* 2 | User/* 3 | TypeScript/* 4 | Preferences.sublime-settings 5 | *.DS_Store 6 | local/* 7 | generated/* 8 | *__pycache__ 9 | .vscode/* 10 | doc.md -------------------------------------------------------------------------------- /snippets/cpp/utility/mainDefault.cpp: -------------------------------------------------------------------------------- 1 | signed main() { 2 | ios::sync_with_stdio(false); 3 | cout.tie(0); cin.tie(0); 4 | cout << fixed << setprecision(10); 5 | 6 | $0 7 | } 8 | -------------------------------------------------------------------------------- /snippets/cpp/definitions/def_consts.cpp: -------------------------------------------------------------------------------- 1 | using lli = long long int; 2 | using llu = unsigned long long int; 3 | using ld = long double; 4 | 5 | const int INF = 1000*1000*1000; 6 | 7 | 8 | -------------------------------------------------------------------------------- /snippets/cpp/utility/mainSimple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | signed main() { 5 | ios::sync_with_stdio(false); 6 | cout.tie(0); cin.tie(0); 7 | 8 | $0 9 | } -------------------------------------------------------------------------------- /snippets/python/main/mainMini.py: -------------------------------------------------------------------------------- 1 | import sys, random, itertools 2 | from copy import copy, deepcopy 3 | from math import * 4 | INF = 10**9 5 | 6 | def main(): 7 | 8 | $0 9 | 10 | main() -------------------------------------------------------------------------------- /snippets/python/algo/general/algo_dicho.py: -------------------------------------------------------------------------------- 1 | a, b = 0, ${1:100} # Include / exclude 2 | while a+1 < b: # We search the first n such as fct(n) is true 3 | m = (a+b-1)//2 4 | if ${2:fct(m)}: 5 | b=m+1 6 | else: 7 | a=m+1 -------------------------------------------------------------------------------- /snippets/cpp/utility/bincludes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | 14 | -------------------------------------------------------------------------------- /genAll.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -r generated/* 3 | python3 scripts/genSubTextSnippets.py && echo "Generated for Sublime Text 3" 4 | python3 scripts/genVSCodeSnippets.py && echo "Generated for VS Code" 5 | python3 scripts/genDoc.py && echo "Documentation generated" 6 | # scripts/mvCodeSnippets.sh -------------------------------------------------------------------------------- /snippets/python/algo/graphs/algo_dfs.py: -------------------------------------------------------------------------------- 1 | dfs_seen = set() 2 | def do_dfs(node): 3 | if node in dfs_seen: 4 | return 0 5 | dfs_seen.add(node) 6 | 7 | all_results = [] 8 | for child in voisins[node]: 9 | r = do_dfs(child) 10 | all_results.append(r) 11 | 12 | return 1 + sum(all_results) -------------------------------------------------------------------------------- /snippets/cpp/io/read/read_flow.cpp: -------------------------------------------------------------------------------- 1 | void readFlow() { 2 | cin >> nbNodes >> nbArcs; 3 | for (int iArc = 0; iArc < nbArcs; iArc++) { 4 | int deb, fin, capArc; 5 | cin >> dev >> fin >> capArc; 6 | cap[deb][fin] += capArc; 7 | if (!IS_FLOW_ORIENTED) { 8 | cap[deb][fin] += capArc; 9 | } 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /snippets/python/util/util_combi.py: -------------------------------------------------------------------------------- 1 | def get_permuts(l,r=None): return list(permutations(l, r)) 2 | 3 | def next_permutation(l): 4 | i=len(l)-2 5 | while i>=0 and l[i+1]<=l[i]:i-=1 6 | if i<0: return l[::-1] 7 | j=i 8 | while j+1=l[i]:j+=1 9 | return l[:i] + [l[j]] + l[j+1:][::-1] + ([l[i]] if i-j else []) + l[i+1:j][::-1] -------------------------------------------------------------------------------- /snippets/cpp/io/read/read_graph.cpp: -------------------------------------------------------------------------------- 1 | void readGraph() { 2 | cin >> nbNodes >> nbArcs; 3 | for (int iArc = 0; iArc < nbArcs; iArc++) { 4 | int node1, node2; 5 | cin >> node1 >> node2; 6 | node1 -= IDS_FIRST; node2 -= IDS_FIRST; 7 | voisins[node1].push_back({node2}); 8 | graph_parents[node2].push_back({node1}); 9 | } 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /scripts/templates/sublimeSnippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | {{{name}}} 7 | 8 | source.{{{lang}}} 9 | 10 | -------------------------------------------------------------------------------- /snippets/python/structs/str_graph.py: -------------------------------------------------------------------------------- 1 | MAX_NODES = 10**4 2 | G_FIRST_ID = 0 3 | 4 | G_PONDERE = False 5 | G_ORIENTED = False 6 | 7 | Arc = namedtuple('Arc', ['dest', 'weight'] if G_PONDERE else ['dest']) 8 | 9 | voisins = [[] for _ in range(MAX_NODES)] 10 | G_parents = [[] for _ in range(MAX_NODES)] if G_ORIENTED else [] 11 | 12 | nb_nodes, nb_edges = 0, 0 -------------------------------------------------------------------------------- /snippets/cpp/contest_scpecific/codejam_main.cpp: -------------------------------------------------------------------------------- 1 | signed main() { 2 | ios::sync_with_stdio(false); 3 | cout.tie(0); cin.tie(0); 4 | int nbCases; 5 | cin >> nbCases; 6 | 7 | for (int iCase = 1; iCase <= nbCases; iCase++) { 8 | // printf("Case #%d: ", iCase); 9 | cout << "Case #" << iCase << ": "; 10 | 11 | $0 12 | 13 | // printf("\n"); 14 | cout << "\n"; 15 | } 16 | } -------------------------------------------------------------------------------- /snippets/cpp/io/read/read_graph_pondere.cpp: -------------------------------------------------------------------------------- 1 | void readGraphPondere() { 2 | cin >> nbNodes >> nbArcs; 3 | for (int iArc = 0; iArc < nbArcs; iArc++) { 4 | int node1, node2, size; 5 | cin >> node1 >> node2 >> size; 6 | node1 -= IDS_FIRST; node2 -= IDS_FIRST; 7 | voisins[node1].push_back({node2, size}); 8 | graph_parents[node2].push_back({node1, size}); 9 | } 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /snippets/cpp/io/convertion/grid_to_graph.cpp: -------------------------------------------------------------------------------- 1 | for (int lig = 0; lig < nbLigs; lig++) { 2 | for (int col = 0; col < nbCols; col++) { 3 | int id = getCellId({lig, col}); 4 | if (isPosValid({lig, col})) { 5 | for (auto& mv : moves) { 6 | Pos next = Pos{lig, col} + mv; 7 | if (isPosValid(next)) { 8 | int id2 = getCellId(next); 9 | voisins[id].push_back({id2}); 10 | } 11 | } 12 | } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /snippets/cpp/algo/general/algo_dicho.cpp: -------------------------------------------------------------------------------- 1 | //@title Dichotomy algorithm 2 | //@doc This snippet is not a function and must be inserted directly into the code 3 | //@ 4 | int deb = 0, fin = ${1:10*1000}; 5 | while (deb+1 < fin) { 6 | int center = (deb + fin)/2; 7 | if (${2:some_function(center)} > ${3:target}) { // on garde partie supérieure 8 | fin = center; 9 | } else { // partie inférieure 10 | deb = center; 11 | } 12 | } 13 | $0 14 | -------------------------------------------------------------------------------- /snippets/python/algo/general/algo_union_find.py: -------------------------------------------------------------------------------- 1 | NB_ELEMS = 1000 2 | 3 | UF_parent = [-1]*NB_ELEMS 4 | UF_rank = [1]*NB_ELEMS 5 | 6 | def Find(a): 7 | if UF_parent[a] == -1: return a 8 | UF_parent[a] = Find(UF_parent[a]) 9 | return UF_parent[a] 10 | 11 | def Union(a, b): 12 | a, b = Find(a), Find(b) 13 | if a==b:return False 14 | if UF_rank[a] < UF_rank[b]: a, b = b, a 15 | UF_rank[a], UF_parent[b] = max(UF_rank[a], UF_rank[b]+1), a 16 | return True -------------------------------------------------------------------------------- /scripts/mvCodeSnippets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ -z "$VSCODE_SNIPPETS" ] 3 | then 4 | echo "Please set \$VSCODE_SNIPPETS to your VS Code user snippets directory if you want this script to automaticly copy the VS Code snippets file to your snippets directory" 5 | else 6 | cp generated/vscodeSnippets/competitive_snippets.code-snippets "$VSCODE_SNIPPETS/competitive_snippets.code-snippets" && echo "competitive_snippets.code-snippets has been copied in $VSCODE_SNIPPETS" 7 | fi -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/shortest_path/algo_remonte_dijkstra.cpp: -------------------------------------------------------------------------------- 1 | vector remonte_dijkstra(int node) { 2 | vector soluce = {node}; 3 | while (dij_t_min[node] != 0) { 4 | for (auto& arc : graph_parents[node]) { 5 | if (dij_t_min[arc.dest] + arc.size == dij_t_min[node]) { 6 | node = arc.dest; 7 | break; 8 | } 9 | } 10 | soluce.push_back(node); 11 | } 12 | reverse(soluce.begin(), soluce.end()); 13 | return soluce; 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /snippets/python/util/util_sequences_str.py: -------------------------------------------------------------------------------- 1 | def max_2ffix_of_prefixs(seq): 2 | max_len = [0]*len(seq) 3 | prev_len = 0 4 | for i_el in range(1, len(seq)): 5 | while True: 6 | if seq[prev_len] == seq[i_el]: 7 | prev_len += 1 8 | break 9 | elif prev_len > 0: 10 | prev_len = max_len[prev_len-1] 11 | else: 12 | break 13 | max_len[i_el] = prev_len 14 | return max_len 15 | 16 | def max_2ffix_of_suffixs(seq): 17 | return max_2ffix_of_prefixs(seq[::-1])[::-1] -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/shortest_path/algo_remonte_bfs.cpp: -------------------------------------------------------------------------------- 1 | vector bfsRemonte(int node) { 2 | vector path; 3 | while (node != -1) { 4 | path.push_back(node); 5 | if (bfs_tMin[node] == 0) { 6 | node = -1; 7 | } else { 8 | for (auto& arc : voisins[node]) { 9 | if (bfs_tMin[arc.dest] == bfs_tMin[node]-1) { 10 | node = arc.dest; 11 | break; 12 | } 13 | } 14 | } 15 | } 16 | reverse(path.begin(), path.end()); 17 | return path; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /snippets/cpp/io/read/read_max_matching.cpp: -------------------------------------------------------------------------------- 1 | void readMaxMatching() { // Default: biparty graph 2 | cin >> nbVerticesSet1 >> nbVerticesSet2 >> nbEdges; 3 | nbVertices = nbVerticesSet1 + nbVerticesSet2; 4 | 5 | for (int iEdge = 0; iEdge < nbEdges; iEdge++) { 6 | int iVertex1, iVertex2; 7 | cin >> iVertex1 >> iVertex2; 8 | iVertex2 += nbVerticesSet1; // Re-index 9 | 10 | voisins[iVertex1].push_back(iVertex2); 11 | voisins[iVertex2].push_back(iVertex1); 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /snippets/cpp/contest_scpecific/battleDev_main.cpp: -------------------------------------------------------------------------------- 1 | #ifdef on_local 2 | struct ContestExerciseImpl { void main(); }; 3 | void localPrint(string s) {cerr << s << "\n";} 4 | int main() { ContestExerciseImpl().main(); } 5 | #else 6 | #include "exercise.hpp" 7 | ContestExerciseImpl::ContestExerciseImpl() : Exercise() {} 8 | #endif 9 | 10 | void ContestExerciseImpl::main() { // You can use localPrint(string) 11 | ios::sync_with_stdio(false); 12 | cout.tie(0); cin.tie(0); 13 | 14 | $0 15 | } 16 | -------------------------------------------------------------------------------- /snippets/python/algo/general/algo_merge_sort.py: -------------------------------------------------------------------------------- 1 | def merge_sort(seq): 2 | if len(seq)<2: return seq 3 | n = len(seq)//2 4 | left, right = merge_sort(seq[:n]), merge_sort(seq[n:]) 5 | i, j, n, m, seq = 0, 0, len(left), len(right), [] 6 | 7 | while i < n and j < m: 8 | if left[i] < right[j]: # 9 | seq.append(left[i]) 10 | i += 1 11 | else: 12 | seq.append(right[j]) 13 | j += 1 14 | seq.extend(left[i:]) 15 | seq.extend(right[j:]) 16 | return seq 17 | 18 | $0 -------------------------------------------------------------------------------- /snippets/python/util/util_search.py: -------------------------------------------------------------------------------- 1 | def lower_bound(n, l): 2 | a, b = 0, len(l) 3 | while a+1= n: b = m+1 6 | else: a = m+1 7 | return a 8 | 9 | def upper_bound(n, l): 10 | a, b = 0, len(l) 11 | while a+1 voisins[MAX_NODES+IDS_FIRST]; 18 | #ifdef GRAPH_ORIENTED 19 | vector graph_parents[MAX_NODES+IDS_FIRST]; 20 | #else 21 | auto &graph_parents = voisins; 22 | #endif 23 | int nbNodes, nbArcs; 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /snippets/cpp/algo/general/algo_union_find.cpp: -------------------------------------------------------------------------------- 1 | //@title Union-Find algorithm 2 | //@defines Union Find 3 | //@ 4 | struct Uf { 5 | vector parent; 6 | vector compoSize; 7 | Uf(int nbNodes) {parent.resize(nbNodes, -1);compoSize.resize(nbNodes, 1);} 8 | 9 | int Find(int a) { return parent[a] == -1 ? a : (parent[a] = Find(parent[a])); } 10 | int Union(int a, int b) { 11 | a = Find(a), b = Find(b); 12 | if (a != b) { 13 | if (compoSize[a] < compoSize[b]) { 14 | swap(a, b); 15 | } 16 | parent[b] = a; 17 | compoSize[a] += compoSize[b]; 18 | return compoSize[a]; 19 | } 20 | return 0; 21 | } 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /snippets/cpp/io/read/read_min_cost_flow.cpp: -------------------------------------------------------------------------------- 1 | void readMinCostFlow() { 2 | cin >> nbVertices >> nbEdges >> source >> puit; 3 | fill(cap[0], cap[0] + MAX_VERTICES*MAX_VERTICES, 0); 4 | fill(cost[0], cost[0] + MAX_VERTICES*MAX_VERTICES, 0); 5 | 6 | for (int iEdge = 0; iEdge < nbEdges; iEdge++) { 7 | int vertex1, vertex2, capVertex, costVertex; 8 | cin >> vertex1 >> vertex2 >> capVertex >> costVertex; 9 | 10 | cost[vertex1][vertex2] = costVertex; 11 | cap[vertex1][vertex2] = capVertex; 12 | 13 | /* If not oriented, add the reverse edges 14 | cost[vertex2][vertex1] = costVertex; 15 | cap[vertex2][vertex1] = capVertex; //*/ 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /snippets/cpp/io/convertion/grid_to_flow.cpp: -------------------------------------------------------------------------------- 1 | for (int lig = 0; lig < nbLigs; lig++) { 2 | for (int col = 0; col < nbCols; col++) { 3 | int id = getCellId({lig, col})*2+2; 4 | if (grid[lig][col] == 'c') { 5 | cap[0][id] = INF; 6 | } 7 | if (grid[lig][col] == 'p') { 8 | cap[id+1][1] = INF; 9 | } 10 | cap[id][id+1] = INF; 11 | if (grid[lig][col] == '?') { 12 | cap[id][id+1] = 1; 13 | } 14 | if (isPosValid({lig, col})) { 15 | for (auto& mv : moves) { 16 | Pos next = Pos{lig, col} + mv; 17 | if (isPosValid(next)) { 18 | int id2 = getCellId(next)*2+2; 19 | cap[id+1][id2] = INF; 20 | } 21 | } 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/algo_dfs.cpp: -------------------------------------------------------------------------------- 1 | const char DFS_PAS_VU = 0, DFS_EN_COURS = 1, DFS_VU = 2; 2 | char dfs_state[MAX_NODES]; 3 | 4 | int dfs_recur(int node) { 5 | if (dfs_state[node] != DFS_PAS_VU) { 6 | return 0; 7 | } 8 | dfs_state[node] = true; 9 | 10 | for (auto v : voisins[node]) { 11 | if (dfs_state[v.dest] == DFS_PAS_VU) { 12 | int result = dfs_recur(v.dest); 13 | } else if (dfs_state[v.dest] == DFS_EN_COURS) { 14 | 15 | } 16 | } 17 | return 0; 18 | } 19 | 20 | void start_dfs() { 21 | for (int iNode = 0; iNode < nbNodes; iNode++) { 22 | if (dfs_state[iNode] == DFS_PAS_VU) { 23 | int result = dfs_recur(iNode); 24 | } 25 | } 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /snippets/python/algo/graphs/algo_bellman_ford.py: -------------------------------------------------------------------------------- 1 | def bellman_ford(edges, sources, times=None, steps=None): 2 | # edges : [(vertex_from, vertex_to, length)] 3 | if times is None: 4 | times = {k:0 for k in sources} 5 | for e_from, e_to, _ in edges: 6 | times[e_from] = times.get(e_from, LLINF) 7 | times[e_to] = times.get(e_to, LLINF) 8 | else: 9 | times = copy(times) 10 | if steps is None: 11 | steps = len(times) 12 | 13 | for _ in range(steps): 14 | times_prev = times 15 | # times_prev = copy(times) # 16 | for e_from, e_to, length in edges: 17 | times[e_to] = min(times[e_to], times_prev[e_from] + length) 18 | return times -------------------------------------------------------------------------------- /scripts/genSubTextSnippets.py: -------------------------------------------------------------------------------- 1 | import os, utils 2 | 3 | SNIPPET_FOLDER = "generated/sublimeTextSnippets" 4 | LANGS = { 5 | "cpp": "c++", 6 | "py": "python" 7 | } 8 | 9 | for snippet in utils.getAllSnippets(): 10 | newDirPath = os.path.join(SNIPPET_FOLDER, snippet['dirpath']) 11 | os.makedirs(newDirPath, exist_ok=True) 12 | 13 | newPath = os.path.join(newDirPath, snippet['name'] + '.sublime-snippet') 14 | content = "\n".join(snippet["code"]) 15 | content = utils.insertInTemplate("scripts/templates/sublimeSnippet", { 16 | "content": content, 17 | "name": snippet['name'], 18 | "lang": LANGS[snippet['lang']], 19 | }) 20 | 21 | with open(newPath, "w") as f: 22 | f.write(content) -------------------------------------------------------------------------------- /snippets/cpp/algo/geometry/geo_rects.cpp: -------------------------------------------------------------------------------- 1 | // Geometry functions for rectangles. Requires geo_base 2 | 3 | struct Rect { // Defined by min x/y and max x/y corners 4 | Vect cor1, cor2; 5 | vint area(){ Vect diag = cor2 - cor1; return abs(diag.x * diag.y); } 6 | Rect intersect(const Rect& other) { 7 | Rect r = {{max(cor1.x, other.cor1.x), max(cor1.y, other.cor1.y)}, 8 | {min(cor2.x, other.cor2.x), min(cor2.y, other.cor2.y)}}; 9 | r.cor2 = {max(r.cor1.x, r.cor2.x), max(r.cor1.y, r.cor2.y)}; 10 | return r; 11 | } 12 | }; 13 | ostream& operator<<(ostream& os, const Rect& r) { os << r.cor1 << " " << r.cor2; return os; } 14 | istream& operator>>(istream& is, Rect& r) { is >> r.cor1 >> r.cor2; return is; } -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/algo_contain_cycle.cpp: -------------------------------------------------------------------------------- 1 | int gcc_state[MAX_NODES]; 2 | 3 | bool __graph_contain_cycle_recur(int node) { 4 | gcc_state[node] = 1; 5 | for (Arc arc : voisins[node]) { 6 | int v = arc.dest; 7 | if (gcc_state[v] == 1) { 8 | return true; 9 | } 10 | if (gcc_state[v] == 0 && __graph_contain_cycle_recur(v)) { 11 | return true; 12 | } 13 | } 14 | gcc_state[node] = 2; 15 | return false; 16 | } 17 | 18 | bool graph_contain_cycle() { 19 | fill(gcc_state, gcc_state+nbNodes, 0); 20 | for (int iNode = 0; iNode < nbNodes; iNode++) { 21 | if (gcc_state[iNode] == 0) { 22 | if (__graph_contain_cycle_recur(iNode)) { 23 | return true; 24 | } 25 | } 26 | } 27 | return false; 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /snippets/cpp/tools/tool_reindexer.cpp: -------------------------------------------------------------------------------- 1 | template struct Reindexer { 2 | vector vals; 3 | void add(T v){vals.push_back(v);} 4 | void add(vector vs){for (auto v : vs){vals.push_back(v);}} 5 | void sort() { 6 | std::sort(vals.begin(), vals.end()); 7 | vector vals2; 8 | for (auto& el : vals) { 9 | if (vals2.empty() || vals2.back() != el) { 10 | vals2.push_back(el); 11 | } 12 | } 13 | vals = vals2; 14 | } 15 | int get(T v) { 16 | int a = 0, b = vals.size(); 17 | while (a < b-1) { 18 | int m = (a+b)/2; 19 | if (vals[m] == v) { 20 | return m; 21 | } else if (vals[m] < v) { 22 | a = m+1; 23 | } else { 24 | b = m; 25 | } 26 | } 27 | return a; 28 | } 29 | int size() { 30 | return vals.size(); 31 | } 32 | }; -------------------------------------------------------------------------------- /snippets/python/algo/flows/algo_min_cut.py: -------------------------------------------------------------------------------- 1 | # 2 | 3 | def min_cut_from_flow(sources, flow, capacity): 4 | voisins = voisins_from_edges([(e1, e2, c) for (e1, e2), c in capacity.items() if c > 0]) 5 | 6 | seen_nodes = set() 7 | for src in sources: 8 | if src not in seen_nodes: 9 | stack = [src] 10 | seen_nodes.add(src) 11 | while stack: 12 | node = stack.pop() 13 | for vois in voisins[node]: 14 | if vois not in seen_nodes and flow[(node, vois)] < capacity[(node, vois)]: 15 | seen_nodes.add(vois) 16 | stack.append(vois) 17 | 18 | cut_edges = [e for e, cap in capacity.items() 19 | if cap > 0 and cap == flow[e] and e[0] in seen_nodes and e[1] not in seen_nodes 20 | ] 21 | 22 | return cut_edges -------------------------------------------------------------------------------- /snippets/python/structs/str_heap.py: -------------------------------------------------------------------------------- 1 | class Heap(): # Smaller on top 2 | def __init__(self, l=None): 3 | self.l = copy(l or []) 4 | if self.l: heapq.heapify(self.l) 5 | def push(self, el): return heapq.heappush(self.l, el) 6 | def top(self): return self.l[0] 7 | def pop(self): return heapq.heappop(self.l) 8 | def size(self): return len(self.l) 9 | def is_empty(self): return self.l == [] 10 | def clear(self): self.l = [] 11 | 12 | class HeapWithKey(Heap): 13 | def __init__(self, key, l=None): # Smaller key on top 14 | self.key = key 15 | super().__init__([(key(v), v) for v in (l or [])]) 16 | def push(self, el): return heapq.heappush(self.l, (key(el), el)) 17 | def top(self): return self.l[0][1] 18 | def pop(self): return heapq.heappop(self.l)[1] 19 | 20 | $0 -------------------------------------------------------------------------------- /scripts/genVSCodeSnippets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import utils 4 | 5 | SNIPPET_FOLDER = "generated/vscodeSnippets" 6 | SNIPPET_FILE_NAME = "competitive_snippets.code-snippets" 7 | SNIPPET_FILE = os.path.join(SNIPPET_FOLDER, SNIPPET_FILE_NAME) 8 | 9 | snippetsDatas = {} 10 | 11 | langToScope = { 12 | 'py': 'python', 13 | } 14 | 15 | for snippet in utils.getAllSnippets(): 16 | snippetsDatas[snippet['name']] = { 17 | 'prefix': snippet['name'], 18 | 'body': snippet['code'], 19 | 'description': "\n".join(snippet['properties']['doc']), 20 | 'scope': langToScope.get(snippet['lang'], snippet['lang']), 21 | } 22 | 23 | os.makedirs(SNIPPET_FOLDER, exist_ok=True) 24 | with open(SNIPPET_FILE, "w") as f: 25 | json.dump(snippetsDatas, f) 26 | -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/shortest_path/algo_bfs.cpp: -------------------------------------------------------------------------------- 1 | //@ 2 | //@title Algo de BFS 3 | //@ 4 | using BFS_Sit = int; 5 | 6 | int bfs_tMin[MAX_NODES+1]; 7 | 8 | struct __BFS_Init { 9 | __BFS_Init() { 10 | fill(bfs_tMin, bfs_tMin + MAX_NODES, INF); 11 | } 12 | } __bFS_Init; 13 | 14 | void bfsFrom(vector sources) { 15 | fill(bfs_tMin, bfs_tMin+nbNodes+1, INF); 16 | 17 | deque bfsQ; 18 | for (BFS_Sit& s : sources) { 19 | bfs_tMin[s] = 0; 20 | bfsQ.push_back(s); 21 | } 22 | 23 | while (!bfsQ.empty()) { 24 | BFS_Sit node = bfsQ.front(); 25 | bfsQ.pop_front(); 26 | for (auto& v : voisins[node]) { 27 | if (bfs_tMin[v.dest] == INF) { 28 | bfs_tMin[v.dest] = bfs_tMin[node] + 1; 29 | bfsQ.push_back(v.dest); 30 | } 31 | } 32 | } 33 | } 34 | 35 | void bfsFrom(BFS_Sit source) { bfsFrom({source}); } -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/shortest_path/algo_bellman_ford.cpp: -------------------------------------------------------------------------------- 1 | #define BF_COMP min 2 | 3 | vector bf_times_save; 4 | vector bf_times; 5 | 6 | void __apply_bf() { 7 | for (int turn = 0; turn < nbNodes; turn++) { 8 | for (int iNode = 0; iNode < nbNodes; iNode++) { 9 | if (bf_times[iNode] != INF) { 10 | for (auto& arc : voisins[iNode]) { 11 | bf_times[arc.dest] = BF_COMP(bf_times[arc.dest], bf_times[iNode] + arc.size); 12 | } 13 | } 14 | } 15 | } 16 | } 17 | 18 | bool bellman_ford(vector sources) { 19 | bf_times.resize(nbNodes, sources.empty() ? 0 : INF); 20 | for (auto& el : sources) { 21 | bf_times[el] = 0; 22 | } 23 | __apply_bf(); 24 | bf_times_save = bf_times; 25 | __apply_bf(); 26 | 27 | if (bf_times_save != bf_times) { 28 | return true; 29 | } 30 | return false; 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /snippets/cpp/utility/string_utility.cpp: -------------------------------------------------------------------------------- 1 | vector split(string str, char delim=' ') { 2 | size_t current, previous = 0; 3 | vector cont; 4 | current = str.find(delim); 5 | while (current != string::npos) { 6 | cont.push_back(str.substr(previous, current - previous)); 7 | previous = current + 1; 8 | current = str.find(delim, previous); 9 | } 10 | cont.push_back(str.substr(previous, current - previous)); 11 | return cont; 12 | } 13 | 14 | string& ltrim(string& s) { 15 | auto it = find_if(s.begin(), s.end(),[](char c) {return !isspace(c, locale::classic());}); 16 | s.erase(s.begin(), it); return s;} 17 | string& rtrim(string& s) { 18 | auto it = find_if(s.rbegin(), s.rend(),[](char c) {return !isspace(c, locale::classic());}); 19 | s.erase(it.base(), s.end());return s;} 20 | string& trim(string s) { return ltrim(rtrim(s)); } -------------------------------------------------------------------------------- /snippets/python/algo/graphs/algo_dij.py: -------------------------------------------------------------------------------- 1 | def do_dij(sources, dij_voisins=None): 2 | tmin, prev = {}, {} 3 | # tmin = [INF] * MAX_NODES 4 | # prev = [None] * MAX_NODES 5 | # dij_voisins = dij_voisins or [[] for _ in range(MAX_NODES + 1)] 6 | 7 | sit_heap = [(0, s) for s in sources] 8 | heapq.heapify(sit_heap) 9 | for _t, _s in sit_heap: 10 | tmin[_s], prev[_s] = _t, None 11 | while sit_heap: 12 | cur_time, pos = heapq.heappop(sit_heap) 13 | if tmin[pos] == cur_time: 14 | for (vois, length) in dij_voisins[pos]: 15 | if cur_time + length < tmin.get(vois, LLINF): 16 | tmin[vois] = cur_time + length 17 | prev[vois] = pos 18 | heapq.heappush(sit_heap, (cur_time + length, vois)) 19 | return tmin, prev 20 | 21 | def get_dij_path(prev, target): 22 | path = [target] 23 | while prev[path[-1]] is not None: 24 | path.append(prev[path[-1]]) 25 | return path[::-1] -------------------------------------------------------------------------------- /snippets/python/extras/str_cartesian_tree_extras.py: -------------------------------------------------------------------------------- 1 | def cart_to_tab_add(tree, l): 2 | if tree: 3 | cart_to_tab_add(tree.left, l) 4 | l.append(tree.val) 5 | cart_to_tab_add(tree.right, l) 6 | 7 | def cart_to_tab(tree): 8 | l = [] 9 | cart_to_tab_add(tree, l) 10 | return l 11 | 12 | def cart_haut(tree): 13 | return 1+max(cart_haut(tree.right), cart_haut(tree.left)) if tree else 0 14 | 15 | def cart_to_str(tree): 16 | if tree == None: 17 | return [] 18 | a, b = cart_to_str(tree.left), cart_to_str(tree.right) 19 | s = "{}[{}]".format(tree.val, tree.rand) 20 | 21 | n = max([len(l) for l in a]) if a else 0 22 | m = max([len(l) for l in b]) if b else 0 23 | while len(a) < len(b): a.append(" "*n) 24 | while len(a) > len(b): b.append(" "*m) 25 | return [" "*n + s + " "*m] + [x + " "*len(s) + y for x, y in zip(a, b)] 26 | 27 | def cart_print(tree): 28 | print("\n".join(cart_to_str(tree))) 29 | 30 | $0 -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/shortest_path/algo_dijkstra.cpp: -------------------------------------------------------------------------------- 1 | int dij_t_min[MAX_NODES]; 2 | 3 | struct Dij_sit { 4 | int pos, time; 5 | }; 6 | bool operator < (const Dij_sit& a, const Dij_sit& b) { 7 | return a.time == b.time ? a.pos > b.pos : a.time > b.time; 8 | } 9 | 10 | void dijkstra(vector sources) { 11 | priority_queue sits; 12 | fill(dij_t_min, dij_t_min+nbNodes, -1); 13 | 14 | for (int p : sources) { 15 | sits.push({p, 0}); 16 | dij_t_min[p] = 0; 17 | } 18 | while (!sits.empty()) { 19 | Dij_sit s = sits.top(); 20 | sits.pop(); 21 | if (s.time == dij_t_min[s.pos]) { 22 | // Parcoure noeud s.pos a s.time 23 | for (auto& arc : voisins[s.pos]) { 24 | if (dij_t_min[arc.dest] == -1 || dij_t_min[arc.dest] > arc.size + s.time) { 25 | dij_t_min[arc.dest] = arc.size + s.time; 26 | sits.push({arc.dest, dij_t_min[arc.dest]}); 27 | } 28 | } 29 | } 30 | } 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /snippets/python/util/util_collections.py: -------------------------------------------------------------------------------- 1 | def argmin(l): return l.index(min(l)) 2 | def argmax(l): return l.index(max(l)) 3 | 4 | def dict_min(d): return min(d.values()) 5 | def dict_max(d): return max(d.values()) 6 | def dict_argmin(d):m = dict_min(d);return [el for el, v in d.items() if v==m][0] 7 | def dict_argmax(d):m = dict_max(d);return [el for el, v in d.items() if v==m][0] 8 | 9 | def uchain(*args):return list(chain(*args)) 10 | def l2str(l,sep=''):return sep.join(map(str, l)) 11 | 12 | class Reindexer: 13 | def __init__(self, l=None): self._l, self._inv = set(l) if l else set(), None 14 | def add(self, x): self._l.add(x) 15 | def build(self): 16 | self._l = list(sorted(self._l)) 17 | self._inv = {x: i for i, x in enumerate(self._l)} 18 | def __getitem__(self, x): return self._inv[x] 19 | def get(self, x): return self._inv[x] 20 | def map(self, xs): return [self._inv[x] for x in xs] 21 | def get_inv(self, i): return self._l[i] -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/flow_max_matching/algo_min_cut.cpp: -------------------------------------------------------------------------------- 1 | vector> minCutArcs; 2 | int minCutIsVisited[MAX_NODES]; 3 | 4 | void minCutMarkNodes(int node) { 5 | if (!minCutIsVisited[node]) { 6 | minCutIsVisited[node] = true; 7 | for (int v = 0; v < MAX_NODES; v++) { 8 | if (flow[node][v] < cap[node][v]) { 9 | minCutMarkNodes(v); 10 | } 11 | } 12 | } 13 | } 14 | 15 | int getMinCut() { // Require algo_flow, return maxFlow, min cut is in minCutArcs 16 | int maxFlow = getMaxFlow(); 17 | fill(minCutIsVisited, minCutIsVisited + MAX_NODES, false); 18 | minCutMarkNodes(sourceId); 19 | 20 | for (int node1 = 0; node1 < MAX_NODES; node1++) { 21 | for (int node2 = 0; node2 < MAX_NODES; node2++) { 22 | if (cap[node1][node2] > 0 && cap[node1][node2] == flow[node1][node2] && minCutIsVisited[node1] && !minCutIsVisited[node2]) { 23 | minCutArcs.push_back({node1, node2}); 24 | } 25 | } 26 | } 27 | return maxFlow; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/flow_max_matching/algo_min_cut_sparse.cpp: -------------------------------------------------------------------------------- 1 | vector minCutEdges; 2 | vector minCutIsVisited; 3 | 4 | void minCutMarkNodes(int iVertex) { 5 | if (!minCutIsVisited[iVertex]) { 6 | minCutIsVisited[iVertex] = true; 7 | for (auto& e : flowEdges[iVertex]) { 8 | if (e.flow < e.cap) { 9 | minCutMarkNodes(e.to); 10 | } 11 | } 12 | } 13 | } 14 | 15 | int getMinCut() { // Require algo_flow_sparse, return maxFlow, min cut is in minCutEdges 16 | int maxFlow = getMaxFlow(); 17 | fill(minCutIsVisited.begin(), minCutIsVisited.end(), false); 18 | minCutIsVisited.resize(nbVertices, false); 19 | minCutEdges.clear(); 20 | 21 | minCutMarkNodes(source); 22 | 23 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 24 | if (minCutIsVisited[iVertex]) { 25 | for (auto& e : flowEdges[iVertex]) { 26 | if (!minCutIsVisited[e.to]) { 27 | minCutEdges.emplace_back(e); 28 | } 29 | } 30 | } 31 | } 32 | return maxFlow; 33 | } -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/algo_tri_topo.cpp: -------------------------------------------------------------------------------- 1 | int atp_nbParents[MAX_NODES]; 2 | 3 | vector tri_topo() { 4 | fill(atp_nbParents, atp_nbParents+nbNodes, 0); 5 | for (int iNode = 0; iNode < nbNodes; iNode++) { 6 | for (auto arc : voisins[iNode]) { 7 | atp_nbParents[arc.dest]++; 8 | } 9 | } 10 | 11 | vector result; 12 | deque waiting_list; 13 | 14 | for (int iNode = 0; iNode < nbNodes; iNode++) { 15 | if (atp_nbParents[iNode] == 0) { 16 | waiting_list.push_back(iNode); 17 | } 18 | } 19 | while (!waiting_list.empty()) { 20 | result.push_back(waiting_list.front()); 21 | for (auto arc : voisins[waiting_list.front()]) { 22 | atp_nbParents[arc.dest]--; 23 | if (atp_nbParents[arc.dest] == 0) { 24 | waiting_list.push_back(arc.dest); 25 | } 26 | } 27 | waiting_list.pop_front(); 28 | } 29 | if ((int)result.size() != nbNodes) { 30 | return {}; 31 | } 32 | return result; 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /snippets/python/util/util_math.py: -------------------------------------------------------------------------------- 1 | def is_prime(n, primes): 2 | for p in primes: 3 | if not n%p: return False 4 | return True 5 | 6 | def crible_primes(borne_max, nb_gen_max=INF): 7 | primes = [] if borne_max < 2 else [2] 8 | for p in range(3, borne_max+1, 2): 9 | if len(primes) >= nb_gen_max: return primes 10 | if is_prime(p, primes): primes.append(p) 11 | return primes 12 | 13 | def gen_n_primes(n): return crible_primes(INF, n) 14 | def gen_primesUnder(p_max): return crible_primes(p_max, INF) 15 | 16 | def get_primes_factors(n): 17 | k, f = 2, [] 18 | while k*k <= n: 19 | while n%k==0: 20 | f.append(k) 21 | n //=k 22 | k+=1 23 | if n > 1: f.append(n) 24 | return f 25 | 26 | def pgcd(a, b): return a if not b else pgcd(b, a%b) 27 | def ppcm(a, b): return a*b // pgcd(a, b) 28 | 29 | def fact(n): return reduce(lambda x,y:x*y, list(range(1,n+1)), 1) # Compute n! 30 | def binom(k, n): return fact(n) // (fact(k) * fact(n-k)) 31 | def is_palindrom(n): return str(n) == str(n)[::-1] 32 | 33 | -------------------------------------------------------------------------------- /snippets/cpp/structs/str_segtree.cpp: -------------------------------------------------------------------------------- 1 | template struct SegTree { 2 | int haut, baseSize, realSize; 3 | vector tree; 4 | SegTree(int size=0, T defVal=T(), T leafVal=T()){resize(size, defVal, leafVal);} 5 | 6 | void resize(int t, T defVal=T(), T leafVal=T()) { 7 | haut = 0, baseSize = 1; 8 | realSize = t; 9 | while (baseSize < t) { haut += 1; baseSize *= 2; } 10 | tree.resize(0); 11 | tree.resize(baseSize*2, defVal); 12 | fill(tree.begin()+baseSize, tree.end(), leafVal); 13 | } 14 | 15 | T& operator[](int i) { return tree[i]; } 16 | T getLeaf(int i) { return tree[i+baseSize]; } 17 | void setLeaf(int i, T val) { tree[i+baseSize] = val; } 18 | void setLeaf(vector vals) { for (int i = 0; i < (int)vals.size(); i++) { tree[i+baseSize] = vals[i]; } } 19 | 20 | inline int borneLeft(const int n) const {int k = (31-__builtin_clz(n));return (1 << (haut-k))*(n-(1< T mergeSort(T elements) { 6 | if (elements.size() >= 2) { 7 | T left, right; 8 | for (int iElement = 0; iElement < (int)elements.size()/2; iElement++) { 9 | left.push_back(elements[iElement]); 10 | } 11 | for (int iElement = (int)elements.size()/2; iElement < (int)elements.size(); iElement++) { 12 | right.push_back(elements[iElement]); 13 | } 14 | left = mergeSort(left); 15 | right = mergeSort(right); 16 | 17 | int i1 = 0, i2 = 0; 18 | while (i1 < (int)left.size()) { 19 | if (i2 >= (int)right.size() || left[i1] < right[i2]) { 20 | elements[i1+i2] = left[i1]; 21 | i1++; 22 | } else { 23 | elements[i1+i2] = right[i2]; 24 | i2++; 25 | } 26 | } 27 | while (i2< (int)right.size()) { 28 | elements[i1+i2] = right[i2]; 29 | i2++; 30 | } 31 | } 32 | return elements; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /snippets/cpp/structs/str_grid.cpp: -------------------------------------------------------------------------------- 1 | //@title Array to represent a grid of char and usefull functions 2 | //@defines grid, readGrid, getCellId, idToCell, isPosValid 3 | //@ 4 | /* Requires st_pos */ 5 | 6 | const bool IS_GRID_SQUARE = true; 7 | const int MAX_COTE = 200; 8 | 9 | int nbLigs, nbCols; 10 | char grid[MAX_COTE][MAX_COTE]; 11 | 12 | void readGrid() { 13 | scanf("%d", &nbLigs); 14 | if (IS_GRID_SQUARE) { 15 | nbCols = nbLigs; 16 | } else { 17 | scanf("%d", &nbCols); 18 | } 19 | 20 | for (int lig = 0; lig < nbLigs; lig++) { 21 | for (int col = 0; col < nbCols; col++) { 22 | scanf(" %c", &grid[lig][col]); 23 | } 24 | } 25 | } 26 | int getCellId(Pos pos) { 27 | int cell = pos.lig*nbCols + pos.col; 28 | return cell; 29 | } 30 | Pos idToCell(int id) { 31 | return {id/nbCols, id%nbCols}; 32 | } 33 | int isPosValid(Pos pos) { 34 | if (pos.lig < 0 || pos.lig >= nbLigs || pos.col < 0 || pos.col >= nbCols) { 35 | return false; 36 | } 37 | if (grid[pos.lig][pos.col] == '#') { 38 | return false; 39 | } 40 | return true; 41 | } 42 | 43 | $0 -------------------------------------------------------------------------------- /snippets/cpp/algo/geometry/geo_shapes.cpp: -------------------------------------------------------------------------------- 1 | // Geometric shapes functions. Requires geo_base + geo_segs 2 | 3 | vector borderToSegs(const vector& border) { 4 | vector v; 5 | if (border.size() >= 2) { 6 | v.emplace_back(Seg{border.back(), border[0]}); 7 | } 8 | for (int i = 0; i < (int)border.size()-1; i++) { 9 | v.emplace_back(Seg{border[i], border[i+1]}); 10 | } 11 | return v; 12 | } 13 | 14 | vector arePointsInArea(const vector& border, const vector& points) { 15 | auto segs = borderToSegs(border); 16 | vector ans; 17 | ans.reserve(border.size()); 18 | for (auto& pt : points) { 19 | Seg s = {pt, Vect{pt.x+1, INF}}; 20 | bool inArea = false; 21 | for (auto& seg : segs) { 22 | if (seg.isOnSeg(pt)) { 23 | inArea = true; 24 | break; 25 | } else if (isThereIntersection(seg, s)) { 26 | inArea = !inArea; 27 | } 28 | } 29 | ans.push_back(inArea); 30 | } 31 | return ans; 32 | } 33 | 34 | bool isPointInArea(const vector& border, Vect point) { return arePointsInArea(border, {point})[0]; } 35 | 36 | $0 -------------------------------------------------------------------------------- /snippets/python/algo/graphs/algo_cfc.py: -------------------------------------------------------------------------------- 1 | def transpose_graph(voisins): 2 | voisins_T = [[] for _ in range(len(voisins))] 3 | for a, l in enumerate(voisins): 4 | for b in l: 5 | voisins_T[b].append(a) 6 | return voisins_T 7 | 8 | def compute_cfc(voisins): 9 | n_nodes = len(voisins) 10 | seen = [False] * n_nodes 11 | seen_order = [] 12 | for start in range(n_nodes): 13 | if not seen[start]: 14 | stack = [(start, 0)] 15 | while stack: 16 | cur, step = stack.pop() 17 | if step == 0 and not seen[cur]: 18 | seen[cur] = True 19 | stack.append((cur, 1)) 20 | stack.extend([(v, 0) for v in voisins[cur] if not seen[v]]) 21 | elif step == 1: 22 | seen_order.append(cur) 23 | 24 | cfcs = [] 25 | seen = [False] * n_nodes 26 | voisins_T = transpose_graph(voisins) 27 | for start in seen_order[::-1]: 28 | if not seen[start]: 29 | cfcs.append([]) 30 | stack = [start] 31 | while stack: 32 | cur = stack.pop() 33 | if not seen[cur]: 34 | seen[cur] = True 35 | cfcs[-1].append(cur) 36 | stack.extend([v for v in voisins_T[cur] if not seen[v]]) 37 | return cfcs -------------------------------------------------------------------------------- /snippets/python/structs/str_deque.py: -------------------------------------------------------------------------------- 1 | class Deque: 2 | def __init__(self, data=None): self._left, self._right = [], list(data) if data is not None else [] 3 | def __len__(self): return len(self._left) + len(self._right) 4 | def __repr__(self): return str(self._left[::-1] + self._right) 5 | def __getitem__(self, i): 6 | ll, lr = len(self._left), len(self._right) 7 | if i < 0: i = ll+lr+i 8 | if i < ll: return self._left[ll-i-1] 9 | return self._right[i-ll] 10 | def __fill_right(self): 11 | x = len(self._left)//2 12 | self._right, self._left = self._left[x::-1], self._left[x:] 13 | def __fill_left(self): 14 | x = len(self._right)//2 15 | self._left, self.right = self._right[x-1::-1], self._right[x:] 16 | 17 | def left(self): return self._left[-1] if self._left else self._right[0] 18 | def right(self): return self._right[-1] if self._right else self._left[0] 19 | def pushleft(self, v): self._left.append(v) 20 | def pushright(self, v): self._right.append(v) 21 | def popleft(self): 22 | if not self._left: self.__fill_left() 23 | return self._left.pop() 24 | def popright(self): 25 | if not self._right: self.__fill_right() 26 | return self._right.pop() 27 | 28 | $0 -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/shortest_path/algo_floyd_warshall.cpp: -------------------------------------------------------------------------------- 1 | //#define GRAPH_ORIENTED 2 | 3 | const int MAX_NODES = 500; 4 | const int IDS_FIRST = 1; 5 | 6 | int nbNodes, nbArcs; 7 | int fw_dists[MAX_NODES][MAX_NODES]; 8 | 9 | void floyd_warshall_init() { 10 | for (int iNode = 0; iNode < nbNodes; iNode++) { 11 | fill(fw_dists[iNode], fw_dists[iNode]+nbNodes, 1000*1000*1000); 12 | fw_dists[iNode][iNode] = 0; 13 | } 14 | } 15 | 16 | void floyd_warshall() { 17 | for (int pivot = 0; pivot < nbNodes; pivot++) { 18 | for (int dest = 0; dest < nbNodes; dest++) { 19 | for (int source = 0; source < nbNodes; source++) { 20 | fw_dists[source][dest] = min(fw_dists[source][dest], fw_dists[source][pivot] + fw_dists[pivot][dest]); 21 | } 22 | } 23 | } 24 | } 25 | 26 | void read_graph_floyd_warshall() { 27 | scanf("%d%d", &nbNodes, &nbArcs); 28 | floyd_warshall_init(); 29 | for (int iArc = 0; iArc < nbArcs; iArc++) { 30 | int node1, node2, size; 31 | scanf("%d%d%d", &node1, &node2, &size); 32 | node1 -= IDS_FIRST; node2 -= IDS_FIRST; 33 | fw_dists[node1][node2] = size; 34 | #ifndef GRAPH_ORIENTED 35 | fw_dists[node2][node1] = size; 36 | #endif 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /snippets/python/structs/str_segtree_sum.py: -------------------------------------------------------------------------------- 1 | class SumSegTree: 2 | def __init__(self, size): 3 | self.size = size 4 | self.real_size = 1 5 | while self.real_size < size: 6 | self.real_size *= 2 7 | 8 | self.val = [0 for _ in range(self.real_size*2)] 9 | 10 | def get_leaf(self, leaf_id): 11 | return self.val[self.real_size + leaf_id] 12 | 13 | def set_leaf(self, leaf_id, new_value): 14 | node_id = self.real_size + leaf_id 15 | self.val[node_id] = new_value 16 | while node_id > 1: 17 | node_id //= 2 18 | self.val[node_id] = self.val[node_id*2] + self.val[node_id*2+1] 19 | 20 | def sum_interval(self, cur_node_id, target_left, target_right, sub_left=None, sub_right=None): 21 | sub_left, sub_right = sub_left or 0, sub_right or self.real_size 22 | 23 | if target_right <= sub_left or target_left >= sub_right: # No intersection 24 | return 0 25 | elif target_left <= sub_left and sub_right <= target_right: # Inside of target 26 | return self.val[cur_node_id] 27 | else: 28 | mid = (sub_left + sub_right) // 2 29 | v1 = self.sum_interval(cur_node_id * 2, target_left, target_right, sub_left, mid) 30 | v2 = self.sum_interval(cur_node_id * 2 + 1, target_left, target_right, mid, sub_right) 31 | return v1 + v2 -------------------------------------------------------------------------------- /snippets/python/algo/convex_hull.py: -------------------------------------------------------------------------------- 1 | def half_convex_hull(points, already_sorted=False): 2 | if not already_sorted: 3 | points.sort() 4 | hull = [] 5 | for pt in points: 6 | while len(hull) >= 2: 7 | a, b = hull[-2], hull[-1] 8 | det = ((b[0]-a[0]) * (pt[1] - a[1]) - (pt[0] - a[0]) * (b[1]-a[1])) 9 | if det < 0: 10 | break 11 | hull.pop() 12 | hull.append(pt) 13 | return hull 14 | 15 | def convex_hull(points): 16 | points.sort() 17 | points1, points2 = [points[0]], [(points[0][0], -points[0][1])] 18 | 19 | for pt in points: 20 | side = (points[-1][0]-points[0][0]) * (pt[1]-points[0][1]) - (pt[0]-points[0][0]) * (points[-1][1]-points[0][1]) 21 | if side > 0: 22 | points1.append(pt) 23 | elif side < 0: 24 | points2.append((pt[0], -pt[1])) 25 | points1.append(points[-1]) 26 | points2.append((points[-1][0], -points[-1][1])) 27 | 28 | hull1 = half_convex_hull(points1, True) 29 | hull2 = half_convex_hull(points2, True) 30 | 31 | for pt in hull2[-2:0:-1]: 32 | hull1.append((pt[0], -pt[1])) 33 | return hull1 34 | 35 | def hull_perimeter(hull): 36 | if not hull: return 0 37 | norm = 0 38 | for i in range(len(hull)): 39 | norm += ((hull[i][0]-hull[i-1][0])**2+(hull[i][1]-hull[i-1][1])**2)**0.5 40 | return norm 41 | 42 | -------------------------------------------------------------------------------- /snippets/python/main/main.py: -------------------------------------------------------------------------------- 1 | import sys, heapq, itertools 2 | from copy import copy, deepcopy 3 | from collections import deque, namedtuple 4 | from itertools import * 5 | from math import * 6 | from random import * # randint, shuffle, ... 7 | from functools import reduce, lru_cache 8 | # from fractions import * 9 | sys.setrecursionlimit(10**9) 10 | 11 | def main(): 12 | INF, LLINF = 10**9, 4*(10**18) 13 | MOD, MOD_EDU = 10**9+7, 998244353 14 | ID_FCT = lambda x:x 15 | # print = sys.stdout.write 16 | # input = sys.stdin.readline 17 | input = lambda : sys.stdin.readline().rstrip() 18 | cache = lru_cache(maxsize=None) 19 | 20 | def modul(n, mod=MOD): return (n%mod + mod)%mod 21 | def err_print(*args, end="\n", sep=" "): sys.stderr.write(" ".join(chain([str(a) for a in args], [end]))) 22 | def list_map(string, fct=int): return list(map(fct, string.split())) 23 | def read_matrix(n, f=ID_FCT): return [list(map(f, sys.stdin.readline().strip().split())) for _ in range(n)] 24 | def read_char_matrix(n): return [sys.stdin.readline().strip() for _ in range(n)] 25 | 26 | 27 | # ------------------------------------------------------------------- 28 | 29 | $0 30 | 31 | # ------------------------------------------------------------------- 32 | 33 | 34 | 35 | main() -------------------------------------------------------------------------------- /snippets/cpp/algo/maths/math_usual.cpp: -------------------------------------------------------------------------------- 1 | //@title Functions for quick access to common mathematical operations 2 | //@defines pgcd, ppcm, genRange, divisorsOf, factorial 3 | //@doc Mathematical functions 4 | //@ 5 | template vector divisorsOf(T n){vector d;for (T k=1;k<=n;k++){if(n%k==0){d.push_back(k);}}return d;} 6 | 7 | template T pgcd(T a, T b) { return (b == 0) ? a : pgcd(b, a%b); } 8 | template T ppcm(T a, T b) { return a * b / pgcd(a, b); } 9 | template T pgcd(vector nums){T r=nums[0];for(int i=1;i<(int)nums.size();i++){r=pgcd(r,nums[i]);}return r;} 10 | template T ppcm(vector nums){T r=nums[0];for(int i=1;i<(int)nums.size();i++){r=ppcm(r,nums[i]);}return r;} 11 | 12 | template vector genRange(T startAt,T endBefore,T step=1) {vector r;while ((step > 0 && startAt < endBefore) || (step < 0 && startAt > endBefore)) {r.push_back(startAt);startAt += step;}return r;} 13 | 14 | template bool isNumPalindrom(T n, T base=10) { 15 | T n2 = n; T inv = 0; while (n2 > 0) { inv = inv * base + n2 % base; n2 /= base; } 16 | return inv == n;} 17 | 18 | template T factorial(T n) {T r=1;while(n){r *= n;n--;}return r;} 19 | template T binom(T k, T n) {T a=1,b=1;while(k){a*=(n-k+1);b*=k;k--;}return a/b;} -------------------------------------------------------------------------------- /snippets/cpp/structs/segtrees/segtree_template.cpp: -------------------------------------------------------------------------------- 1 | //@include structs/str_segtree.cpp 2 | 3 | 4 | template struct ${1:TemplateSegTree} : public SegTree { 5 | $1(int size=0, T defVal=T(), T leafVal=T()):SegTree(size, defVal, leafVal){} 6 | 7 | void initAll() { 8 | auto& tree = *this; 9 | for (int i = this->baseSize-1; i > 0; i--) { 10 | // ... 11 | } 12 | } 13 | 14 | void ${2:pointRequest}(int targetPos, int value) { 15 | auto& tree = *this; 16 | int node = targetPos + this->baseSize; 17 | // Set leaf 18 | 19 | while (node > 1) { 20 | node /= 2; 21 | // Propagate to parents 22 | 23 | } 24 | } 25 | 26 | void ${3:intervalRequest}(int targetLeft, int targetRight, 27 | int curNode=1, int subLeft=0, int subRight=0) { 28 | auto& tree = *this; 29 | if (curNode == 1) { subLeft = 0, subRight = this->baseSize;} 30 | 31 | if (targetRight <= subLeft || targetLeft >= subRight) { 32 | return ; 33 | } else if (!(targetLeft <= subLeft && subRight <= targetRight)) { 34 | int m = (subLeft + subRight) / 2; 35 | ${3}(targetLeft, targetRight, curNode*2, subLeft, m); 36 | ${3}(targetLeft, targetRight, curNode*2+1, m, subRight); 37 | // Do stuff with results here 38 | 39 | return; 40 | } 41 | // Success ! Do your stuff here 42 | 43 | return; 44 | } 45 | }; -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/flow_max_matching/algo_max_matching.cpp: -------------------------------------------------------------------------------- 1 | //@title Maximum matching algorithm 2 | //@defines findMatching, getMaxMatching 3 | //@ 4 | const int MAX_ELEMENTS = 10*1000; 5 | 6 | int linkedTo[MAX_ELEMENTS]; 7 | vector voisins[MAX_ELEMENTS]; 8 | int maxMatchSeen[MAX_ELEMENTS]; 9 | int maxMatchCur = 1; 10 | int nbVertices, nbEdges; 11 | int nbVerticesSet1, nbVerticesSet2; 12 | 13 | bool findMatching(int vertex, bool fromParent) { 14 | if (maxMatchSeen[vertex] == maxMatchCur) { 15 | return false; 16 | } 17 | maxMatchSeen[vertex] = maxMatchCur; 18 | if (linkedTo[vertex] == -1 && not fromParent) { 19 | return true; 20 | } else if (fromParent) { 21 | for (auto& vois : voisins[vertex]) { 22 | if (findMatching(vois, false)) { 23 | linkedTo[vertex] = vois; 24 | linkedTo[vois] = vertex; 25 | return true; 26 | } 27 | } 28 | return false; 29 | } 30 | return findMatching(linkedTo[vertex], true); 31 | } 32 | 33 | int getMaxMatching() { 34 | fill(maxMatchSeen, maxMatchSeen+MAX_ELEMENTS, -1); 35 | fill(linkedTo, linkedTo+MAX_ELEMENTS, -1); 36 | int maxMatch = 0; 37 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 38 | if (linkedTo[iVertex] == -1 && findMatching(iVertex, true)) { 39 | maxMatch++; 40 | } 41 | maxMatchCur++; 42 | } 43 | return maxMatch; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /snippets/python/structs/str_segtree_max.py: -------------------------------------------------------------------------------- 1 | class MaxSegTree: 2 | def __init__(self, size, val_init=-LLINF): 3 | self.size = size 4 | self.real_size = 1 5 | while self.real_size < size: 6 | self.real_size *= 2 7 | 8 | self.val = [-LLINF for _ in range(self.real_size*2)] 9 | for i in range(self.real_size+self.size): 10 | self.val[i] = val_init 11 | 12 | def get_leaf(self, leaf_id): 13 | return self.val[self.real_size + leaf_id] 14 | 15 | def set_leaf(self, leaf_id, new_value): 16 | node_id = self.real_size + leaf_id 17 | self.val[node_id] = new_value 18 | while node_id > 1: 19 | node_id //= 2 20 | self.val[node_id] = max(self.val[node_id*2], self.val[node_id*2+1]) 21 | 22 | def max_interval(self, cur_node_id, target_left, target_right, sub_left=None, sub_right=None): 23 | sub_left, sub_right = sub_left or 0, sub_right or self.real_size 24 | 25 | if target_right <= sub_left or target_left >= sub_right: # No intersection 26 | return -LLINF 27 | elif target_left <= sub_left and sub_right <= target_right: # Inside of target 28 | return self.val[cur_node_id] 29 | else: 30 | mid = (sub_left + sub_right) // 2 31 | v1 = self.sum_interval(cur_node_id * 2, target_left, target_right, sub_left, mid) 32 | v2 = self.sum_interval(cur_node_id * 2 + 1, target_left, target_right, mid, sub_right) 33 | return max(v1, v2) -------------------------------------------------------------------------------- /snippets/cpp/structs/segtrees/segtree_sum.cpp: -------------------------------------------------------------------------------- 1 | //@include structs/str_segtree.cpp 2 | 3 | 4 | template struct SumSegTree : public SegTree { 5 | SumSegTree(int size=0, T defVal=0, T leafVal=0):SegTree(size, defVal, leafVal){} 6 | 7 | void initAll() { 8 | auto& tree = *this; 9 | for (int i = this->baseSize-1; i > 0; i--) { 10 | tree[i] = tree[i*2] + tree[i*2+1]; 11 | } 12 | } 13 | 14 | void set(int targetPos, int value) { 15 | auto& tree = *this; 16 | int node = targetPos + this->baseSize; 17 | tree[node] = value; 18 | while (node > 1) { 19 | node /= 2; 20 | tree[node] = tree[node*2] + tree[node*2+1]; 21 | } 22 | } 23 | void add(int targetPos, int value) { set(targetPos, (*this)[targetPos+this->baseSize] + value); } 24 | 25 | T sumInter(int targetLeft, int targetRight, 26 | int curNode=1, int subLeft=0, int subRight=0) { 27 | auto& tree = *this; 28 | if (curNode == 1) { subLeft = 0, subRight = this->baseSize;} 29 | 30 | if (targetRight <= subLeft || targetLeft >= subRight) { 31 | return 0; 32 | } else if (!(targetLeft <= subLeft && subRight <= targetRight)) { 33 | int m = (subLeft + subRight) / 2; 34 | T a = sumInter(targetLeft, targetRight, curNode*2, subLeft, m); 35 | T b = sumInter(targetLeft, targetRight, curNode*2+1, m, subRight); 36 | 37 | return a+ b; 38 | } 39 | return tree[curNode]; 40 | } 41 | }; -------------------------------------------------------------------------------- /snippets/cpp/structs/str_pos.cpp: -------------------------------------------------------------------------------- 1 | //@title Functions for manipulating 2D integer positions 2 | //@defines Pos, NB_MOVES, moves, movesDir, getMoveId, isPosValid 3 | //@ 4 | #define NB_MOVES 4 5 | 6 | struct Pos { 7 | int lig, col; 8 | }; 9 | Pos operator + (const Pos& a, const Pos& b) { return {a.lig + b.lig, a.col + b.col}; } 10 | Pos operator - (const Pos& a, const Pos& b) { return {a.lig - b.lig, a.col - b.col}; } 11 | bool operator == (const Pos& a, const Pos& b) { return a.lig == b.lig && a.col == b.col; } 12 | bool operator < (const Pos& a, const Pos& b) { return a.lig == b.lig ? a.col < b.col : a.lig < b.lig; } 13 | 14 | array movesAdj = {{{0, 1}, {-1, 0}, {0, -1}, {1, 0}}}; 15 | array movesDirAdj = {{'E', 'N', 'W', 'S'}}; 16 | array movesDiag = {{{-1, 1}, {-1, -1}, {1, -1}, {1, 1}}}; 17 | array movesAdjDiags = {{{0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}}}; 18 | 19 | 20 | #if NB_MOVES == 4 21 | auto moves = movesAdj; auto movesDir = movesAdj; 22 | #elif NB_MOVES == 8 23 | auto moves = movesDiag; 24 | #else 25 | auto moves = movesAdjDiags; 26 | #endif 27 | 28 | int getMoveId(Pos mv) { for (int i = 0; i < NB_MOVES; i++) { if (moves[i] == mv) { return i; } }return -1; } 29 | int isPosValid(Pos pos, int afterMaxLig, int afterMaxCol, int minLig=0, int minCol = 0) { 30 | return pos.lig >= minLig && pos.lig < afterMaxLig && pos.col >= minCol && pos.col < afterMaxCol; 31 | } 32 | 33 | $0 -------------------------------------------------------------------------------- /snippets/python/algo/graphs/algo_bfs.py: -------------------------------------------------------------------------------- 1 | def do_bfs_list(sources, bfs_voisins=None): 2 | bfs_t_tmin = [INF] * MAX_NODES 3 | prev = [None] * MAX_NODES 4 | queue = copy(sources) 5 | for src in queue: 6 | bfs_t_tmin[src] = 0 7 | cur_pos_id = 0 8 | while cur_pos_id < len(queue): 9 | cur_pos = queue[cur_pos_id] 10 | cur_pos_id += 1 11 | cur_voisins = bfs_voisins[cur_pos] # 12 | for vois in cur_voisins: 13 | if bfs_t_tmin[vois] == INF: 14 | bfs_t_tmin[vois] = bfs_t_tmin[cur_pos]+1 15 | prev[vois] = cur_pos 16 | queue.append(vois) 17 | return bfs_t_tmin, prev 18 | 19 | def do_bfs_any(sources, bfs_voisins=None): 20 | bfs_t_tmin, prev = {}, {} 21 | queue = deque(copy(sources)) 22 | for src in queue: 23 | bfs_t_tmin[src] = 0 24 | prev[src] = None 25 | while queue: 26 | cur_pos = queue.popleft() 27 | cur_voisins = bfs_voisins[cur_pos] # 28 | # cur_voisins = [(x+dx, y+dy) for dx, dy in moves if is_pos_valid(x+dx, y+dy, n)] 29 | for vois in cur_voisins: 30 | if vois not in bfs_t_tmin: 31 | dt = 1 # # 1 if grid[vois[0]][vois[1]] == ? else 0 32 | bfs_t_tmin[vois] = bfs_t_tmin[cur_pos]+dt 33 | prev[vois] = cur_pos 34 | if dt: queue.append(vois) 35 | else: queue.appendleft(vois) 36 | return bfs_t_tmin, prev 37 | 38 | def get_bfs_path(prev, target): 39 | path = [target] 40 | while prev[path[-1]] is not None: 41 | path.append(prev[path[-1]]) 42 | return path[::-1] -------------------------------------------------------------------------------- /snippets/cpp/algo/maths/math_primes.cpp: -------------------------------------------------------------------------------- 1 | //@title Functions for quick access to common mathematical operations 2 | //@defines crible_primes, genNPrimes, genNPrimesLli, genPrimesUnder, genPrimesUnderLli 3 | //@doc Include functions for prime numbers 4 | //@ 5 | /* Return a vector of all the prime factors of an integer, in ascending order */ 6 | template vector getPrimeFactors(T n) { 7 | T k = 2; vector factors; 8 | while (k*k <= n) { 9 | if (n%k == 0) { 10 | factors.push_back(k); 11 | n /= k; 12 | } else { k++; } 13 | } if (n > 1) { factors.push_back(n); } 14 | return factors; 15 | } 16 | 17 | template vector crible_primes(T borneMax, int nbGenMax = INF) { 18 | vector primesTab; 19 | if (borneMax >= 2) { primesTab = {2}; } 20 | for (T p = 3; p <= borneMax && (int)primesTab.size() < nbGenMax; p += 2) { 21 | bool isPrime = true; 22 | for (auto pp : primesTab) { 23 | if (p%pp == 0) { 24 | isPrime = false; 25 | break; 26 | }} if (isPrime) { primesTab.push_back(p); } 27 | } return primesTab; 28 | } 29 | vector genNPrimes(int nbPrimesYouWant) { return crible_primes(INF, nbPrimesYouWant); } 30 | vector genNPrimesLli(lli nbPrimesYouWant) { return crible_primes(LLINF, nbPrimesYouWant); } 31 | vector genPrimesUnder(int borneMax) { return crible_primes(borneMax, INF); } // Including 'borneMax' 32 | vector genPrimesUnderLli(lli borneMax) { return crible_primes(borneMax, INF); }// Including 'borneMax' -------------------------------------------------------------------------------- /scripts/genDoc.py: -------------------------------------------------------------------------------- 1 | import os, json, utils 2 | import pprint 3 | 4 | DOC_FILE = "doc.md" 5 | INDENT = " " 6 | 7 | def genSnippetDoc(snippet, docLines, level): 8 | docLines.append(INDENT*level + "- `" + snippet["name"] + "`") 9 | subPrefix = INDENT*(level+1) + "- " 10 | props = snippet["properties"] 11 | 12 | if props["title"]: 13 | docLines[-1] += (" : " + "| ".join(props["title"])) 14 | 15 | if props["defines"]: 16 | defs = ", ".join(props["defines"]) 17 | defs = ", ".join(["`" + fct.strip() + "`" for fct in defs.split(",")]) 18 | docLines.append(subPrefix + "*Defines*: " + defs) 19 | 20 | if props["doc"]: 21 | doc = "\n".join(props["doc"]) 22 | docLines.append(subPrefix + "*Documentation*: " + doc) 23 | 24 | def genCategoryDoc(category, docLines, level): 25 | if level == 0: 26 | docLines.append("## " + category) 27 | else: 28 | docLines.append(INDENT * (level-1) + "- **" + category + "**") 29 | 30 | def genTreeDoc(tree, docLines): 31 | level = tree["_level_"] 32 | excludeKeys = ["_contain_", "_level_"] 33 | 34 | for snippet in tree["_contain_"]: 35 | genSnippetDoc(snippet, docLines, level) 36 | for category in tree: 37 | if not category in excludeKeys: 38 | genCategoryDoc(category, docLines, level) 39 | genTreeDoc(tree[category], docLines) 40 | 41 | 42 | snippetsDatas = utils.getAllSnippets() 43 | tree = utils.getSnippetsTree(snippetsDatas) 44 | 45 | docLines = [] 46 | genTreeDoc(tree, docLines) 47 | 48 | with open(DOC_FILE, "w") as f: 49 | f.write("\n".join(docLines)) -------------------------------------------------------------------------------- /snippets/cpp/structs/segtrees/segtree_template_old.cpp: -------------------------------------------------------------------------------- 1 | //@include structs/str_segtree.cpp 2 | 3 | 4 | template struct ${1:TemplateSegTree} : public SegTree { 5 | $1(int size=0, T defVal=T(), T leafVal=T()):SegTree(size, defVal, leafVal){} 6 | 7 | void initAll() { 8 | auto& tree = *this; 9 | for (int i = this->baseSize-1; i > 0; i--) { 10 | // ... 11 | } 12 | } 13 | 14 | void ${2:pointRequest}(int targetPos, int value, 15 | int curNode = 1, int subLeft = 0, int subRight = 0) { 16 | auto& tree = *this; 17 | if (curNode == 1) { subLeft = 0, subRight = this->baseSize;} 18 | 19 | if (curNode >= this->baseSize || false) { // If the request must stop here 20 | // Do your stuff here 21 | 22 | } else { 23 | int m = (subLeft + subRight) / 2; 24 | if (targetPos < m) { 25 | ${2}(targetPos, value, curNode*2, subLeft, m); 26 | } else { 27 | ${2}(targetPos, value, curNode*2+1, m, subRight); 28 | } 29 | // Use the result here 30 | } 31 | } 32 | 33 | void ${3:intervalRequest}(int targetLeft, int targetRight, 34 | int curNode=1, int subLeft=0, int subRight=0) { 35 | auto& tree = *this; 36 | if (curNode == 1) { subLeft = 0, subRight = this->baseSize;} 37 | 38 | if (targetRight <= subLeft || targetLeft >= subRight) { 39 | return ; 40 | } else if (!(targetLeft <= subLeft && subRight <= targetRight)) { 41 | int m = (subLeft + subRight) / 2; 42 | ${3}(targetLeft, targetRight, curNode*2, subLeft, m); 43 | ${3}(targetLeft, targetRight, curNode*2+1, m, subRight); 44 | // Do stuff with results here 45 | 46 | return; 47 | } 48 | // Success ! Do your stuff here 49 | 50 | return; 51 | } 52 | }; -------------------------------------------------------------------------------- /snippets/cpp/algo/geometry/geo_convex_hull.cpp: -------------------------------------------------------------------------------- 1 | // Minimum convex hull. Requires geo_base 2 | 3 | vector halfMinimumCvx(vector& points, bool alreadySorted=false) { 4 | vector hull; 5 | if (!alreadySorted) { 6 | sort(points.begin(), points.end()); // Sort by x 7 | } 8 | for (Vect& pt : points) { 9 | while (hull.size() >= 2) { 10 | const Vect& a = hull[hull.size()-2], b = hull.back(); 11 | if (det(b-a, pt-a) < 0) { // '<=' may bause bugs 12 | break; 13 | } 14 | hull.pop_back(); 15 | } 16 | hull.emplace_back(pt); 17 | } 18 | return hull; 19 | } 20 | 21 | vector minConvexHull(vector points) { 22 | sort(points.begin(), points.end()); 23 | vector points1, points2; 24 | points1.emplace_back(points[0]); 25 | points2.emplace_back(Vect{points[0].x, -points[0].y}); 26 | 27 | for (auto& pt : points) { 28 | vint side = det(points.back()-points[0], pt-points[0]); 29 | if (side > 0) points1.emplace_back(pt); 30 | else if (side < 0) points2.emplace_back(Vect{pt.x, -pt.y}); 31 | } 32 | points1.emplace_back(points.back()); 33 | points2.emplace_back(Vect{points.back().x, -points.back().y}); 34 | 35 | vector hull1 = halfMinimumCvx(points1, true); 36 | vector hull2 = halfMinimumCvx(points2, true); 37 | 38 | for (int i = (int)hull2.size()-2; i > 0; i--) { 39 | hull1.emplace_back(Vect{hull2[i].x, -hull2[i].y}); 40 | } 41 | return hull1; 42 | } 43 | 44 | vfloat hullPerimeter(const vector& hull) { 45 | if (hull.empty()) { return 0; } 46 | vfloat per = (hull.back()-hull[0]).norm(); 47 | for (int i = 0; i < (int)hull.size()-1; i++) { 48 | per += (hull[i+1]-hull[i]).norm(); 49 | } 50 | return per; 51 | } -------------------------------------------------------------------------------- /snippets/cpp/algo/geometry/geo_segs.cpp: -------------------------------------------------------------------------------- 1 | // Geometry functions for segments. Requires geo_base 2 | 3 | struct Seg { 4 | Vect pt1, pt2; 5 | vfloat normSquare() { return (pt2-pt1).normSquare(); } 6 | vfloat norm() { return (pt2-pt1).norm(); } 7 | vfloat distTo(Vect pt) { 8 | vfloat proj = projOnLineDistOriented(pt, pt1, pt2); 9 | if (proj >= 0 && proj <= this->norm()) { 10 | return abs(distLineOriented(pt, pt1, pt2)); 11 | } 12 | return min((pt-pt1).norm(), (pt-pt2).norm()); 13 | } 14 | bool isOnLine(Vect point) { return det(point-pt1, pt2-pt1) == 0; } 15 | bool isOnSeg(Vect point) { 16 | auto v = (point-pt1) * (pt2-pt1); 17 | return det(point-pt1, pt2-pt1) == 0 && v >= 0 && v <= this->normSquare(); 18 | } 19 | }; 20 | ostream& operator<<(ostream& os, const Seg& s) { os << s.pt1 << " " << s.pt2; return os; } 21 | istream& operator>>(istream& is, Seg& s) { is >> s.pt1 >> s.pt2; return is; } 22 | vfloat distLineOriented(const Vect& point, const Seg& s) { return distLineOriented(point, s.pt1, s.pt2); } 23 | vfloat projOnLineDistOriented(const Vect& p, const Seg& s){return projOnLineDistOriented(p, s.pt1, s.pt2);} 24 | 25 | Vect intersetLines(const Seg& a, const Seg& b) { // Works only if vint = float / double 26 | return b.pt1 + (det(a.pt2-a.pt1, a.pt2-b.pt1) / (vfloat)det(a.pt2-a.pt1, b.pt2-b.pt1)) * (b.pt2-b.pt1); 27 | } 28 | bool isThereIntersection(const Seg& a, const Seg& b) { 29 | if (det(a.pt2-a.pt1, b.pt2-b.pt1) == 0) return false; 30 | vfloat t1 = (vfloat)det(a.pt2-a.pt1, a.pt2-b.pt1) / (vfloat)det(a.pt2-a.pt1, b.pt2-b.pt1); 31 | vfloat t2 = (vfloat)det(b.pt2-b.pt1, b.pt2-a.pt1) / (vfloat)det(b.pt2-b.pt1, a.pt2-a.pt1); 32 | return 0 <= t1 && t1 <= 1 && 0 <= t2 && t2 <= 1; 33 | } -------------------------------------------------------------------------------- /snippets/cpp/structs/segtrees/segtree_max.cpp: -------------------------------------------------------------------------------- 1 | //@include structs/str_segtree.cpp 2 | 3 | 4 | template struct MaxSegTree : public SegTree { 5 | const static T infty = INF; 6 | MaxSegTree(int size=0, T defVal=-infty, T leafVal=-infty):SegTree(size, defVal, leafVal){} 7 | 8 | void initAll() { 9 | for (int i = this->baseSize-1; i > 0; i--) { 10 | this->tree[i] = max(this->tree[i*2], this->tree[i*2+1]); 11 | } 12 | } 13 | 14 | void setPointVal(int targetPos, int value, 15 | int curNode = 1, int subLeft = 0, int subRight = 0) { 16 | if (curNode == 1) { subLeft = 0, subRight = this->baseSize;} 17 | 18 | if (curNode >= this->baseSize || false) { // If the request must stop here 19 | // Do your stuff here 20 | this->tree[curNode] = value; 21 | } else { 22 | int m = (subLeft + subRight) / 2; 23 | if (targetPos < m) { 24 | setPointVal(targetPos, value, curNode*2, subLeft, m); 25 | } else { 26 | setPointVal(targetPos, value, curNode*2+1, m, subRight); 27 | } 28 | this->tree[curNode] = max(this->tree[curNode*2], this->tree[curNode*2+1]); 29 | } 30 | } 31 | 32 | T getMax(int targetLeft, int targetRight, 33 | int curNode=1, int subLeft=0, int subRight=0) { 34 | if (curNode == 1) { subLeft = 0, subRight = this->baseSize;} 35 | 36 | if (targetRight <= subLeft || targetLeft >= subRight) { 37 | return -infty; 38 | } else if (!(targetLeft <= subLeft && subRight <= targetRight)) { 39 | int m = (subLeft + subRight) / 2; 40 | T r1 = getMax(targetLeft, targetRight, curNode*2, subLeft, m); 41 | T r2 = getMax(targetLeft, targetRight, curNode*2+1, m, subRight); 42 | // Do stuff with results here 43 | 44 | return max(r1, r2); 45 | } 46 | // Success ! Do your stuff here 47 | return this->tree[curNode]; 48 | } 49 | }; -------------------------------------------------------------------------------- /snippets/python/algo/flows/algo_max_flow.py: -------------------------------------------------------------------------------- 1 | def max_flow_of_graph(edges, sources, sinks): 2 | # Edges should be a list of (from, to, flow_cap) 3 | flow = {} 4 | capacity = {} 5 | voisins = {} 6 | if len(sinks) > 5: 7 | sinks = set(sinks) 8 | for e_from, e_to, _ in edges: 9 | capacity[(e_from, e_to)] = 0 10 | capacity[(e_to, e_from)] = 0 11 | flow[(e_from, e_to)] = 0 12 | flow[(e_to, e_from)] = 0 13 | voisins[e_to] = [] 14 | voisins[e_from] = [] 15 | for e_from, e_to, e_cap in edges: 16 | capacity[(e_from, e_to)] += e_cap 17 | voisins[e_to].append(e_from) 18 | voisins[e_from].append(e_to) 19 | 20 | cap_max = max(capacity.values()) 21 | try_to_push = 2**int(log2(max(1, cap_max))) 22 | pushed_flow = 0 23 | 24 | while try_to_push: 25 | for src in sources: 26 | pushed = False 27 | stack = [(src, 0)] 28 | seen_nodes = set([src]) 29 | while stack and not pushed: 30 | node, i_vois = stack.pop() 31 | if node in sinks: 32 | pushed = True 33 | stack.append((node, 0)) 34 | break 35 | 36 | while (i_vois < len(voisins[node]) 37 | and capacity[(node, voisins[node][i_vois])] - flow[(node, voisins[node][i_vois])] < try_to_push): 38 | i_vois += 1 # We want only the residual edges (capacity >= try_to_push) 39 | if i_vois < len(voisins[node]): 40 | next_node = voisins[node][i_vois] 41 | stack.append((node, i_vois+1)) 42 | if not next_node in seen_nodes: 43 | stack.append((next_node, 0)) 44 | seen_nodes.add(next_node) 45 | 46 | if pushed: 47 | pushed_flow += try_to_push 48 | for (e1, _), (e2, _) in zip(stack, stack[1:]): 49 | flow[(e1, e2)] += try_to_push 50 | flow[(e2, e1)] -= try_to_push 51 | break 52 | else: 53 | try_to_push //= 2 54 | 55 | return pushed_flow, flow, capacity 56 | 57 | -------------------------------------------------------------------------------- /snippets/python/algo/flows/algo_max_matching.py: -------------------------------------------------------------------------------- 1 | def max_matching(edges): 2 | # Edges: a list of (vertex_left, vertex_right) edges 3 | n_left = max([e[0] for e in edges] or [-1])+1 4 | n_right = max([e[1] for e in edges] or [-1])+1 5 | is_left_linked = [False] * n_left 6 | right_linked_to = [-1] * n_right 7 | last_seen = [[-1] * n for n in [n_left, n_right]] 8 | voisins = [[[] for _ in range(n)] for n in [n_left, n_right]] 9 | for e1, e2 in edges: 10 | voisins[0][e1].append(e2) 11 | voisins[1][e2].append(e1) 12 | 13 | for start in range(n_left): 14 | if not is_left_linked[start]: 15 | stack = [(0, start, 0)] 16 | found_path = False 17 | while stack and not found_path: 18 | side, node, i_vois = stack.pop() 19 | if i_vois == 0: 20 | last_seen[side][node] = start 21 | 22 | if side == 0: 23 | if i_vois < len(voisins[side][node]): 24 | next_node = voisins[side][node][i_vois] 25 | stack.append((side, node, i_vois+1)) 26 | if last_seen[1 - side][next_node] < start: 27 | stack.append((1 - side, next_node, 0)) 28 | else: 29 | if right_linked_to[node] == -1: 30 | found_path = True 31 | stack.append((side, node, i_vois)) 32 | elif i_vois == 0 and last_seen[1 - side][right_linked_to[node]] < start: 33 | stack.append((side, node, 1)) 34 | stack.append((1 - side, right_linked_to[node], 0)) 35 | if found_path: 36 | for (_, left_node, _), (_, right_node, _) in zip(stack[::2], stack[1::2]): 37 | right_linked_to[right_node] = left_node 38 | is_left_linked[left_node] = True 39 | 40 | # return right_linked_to # 41 | couples = [] 42 | for right, left in enumerate(right_linked_to): 43 | if left != -1: 44 | couples.append((left, right)) 45 | return couples 46 | 47 | -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/flow_max_matching/algo_flow.cpp: -------------------------------------------------------------------------------- 1 | //@title Ford-Fulkerson algorithm with flow of size 2^k 2 | //@defines pushFlow, getMaxFlow 3 | //@doc "flow" will contain the flow passing through an edge (positive or negative). 4 | //@ 5 | const int MAX_NODES = 501; 6 | const bool IS_FLOW_ORIENTED = true; 7 | int sourceId = 1, puitId = 1; 8 | 9 | int cap[MAX_NODES][MAX_NODES]; 10 | int flow[MAX_NODES][MAX_NODES]; 11 | int flowExploMark[MAX_NODES]; 12 | int flowExploMarkId = 1; 13 | int nbNodes, nbArcs; 14 | 15 | struct __Flow__init { 16 | __Flow__init() { 17 | for (int l = 0; l < MAX_NODES; l++) { 18 | fill(cap[l], cap[l]+MAX_NODES, 0); 19 | fill(flow[l], flow[l]+MAX_NODES, 0); 20 | } 21 | fill(flowExploMark, flowExploMark+MAX_NODES, 0); 22 | } 23 | } __flow__init; 24 | 25 | bool pushFlow(int node, int push) { 26 | if (node == puitId) { 27 | return true; 28 | } else if (flowExploMark[node] == flowExploMarkId) { 29 | return false; 30 | } 31 | flowExploMark[node] = flowExploMarkId; 32 | for (int v = 0; v < MAX_NODES; v++) { 33 | if (flow[node][v] + push <= cap[node][v]) { 34 | if (pushFlow(v, push)) { 35 | flow[node][v] += push; 36 | flow[v][node] -= push; 37 | return true; 38 | } 39 | } 40 | } 41 | return false; 42 | } 43 | 44 | int getMaxFlow() { 45 | int tryToPush = 1; 46 | int capMax = 0; 47 | for (int el1 = 0; el1 < MAX_NODES; el1++) { 48 | capMax = max(capMax, *max_element(cap[el1], cap[el1]+MAX_NODES)); 49 | } 50 | while (tryToPush*2 <= capMax) { 51 | tryToPush *= 2; 52 | } 53 | int pushedFlow = 0; 54 | while (tryToPush) { 55 | while (++flowExploMarkId && pushFlow(sourceId, tryToPush)) { 56 | pushedFlow += tryToPush; 57 | if (pushedFlow >= INF) { 58 | return INF; 59 | } 60 | } 61 | tryToPush /= 2; 62 | } 63 | return pushedFlow; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /snippets/python/util/util_points_geo.py: -------------------------------------------------------------------------------- 1 | moves = [(0, 1), (-1, 0), (0, -1), (1, 0)] 2 | moves_char = ['E', 'N', 'O', 'S'] 3 | moves_diag = [(-1, 1), (-1, -1), (1, -1), (1, 1)] 4 | moves_all = moves + moves_diag 5 | 6 | def is_pos_valid(x, y, max_x, max_y=None): 7 | if max_y is None: max_y = max_x 8 | # return 0 < x <= max_x and 0 < y <= max_y # 9 | return 0 <= x < max_x and 0 <= y < max_y 10 | 11 | def add_vect(a, b): return [x+y for x, y in zip(a, b)] 12 | def sub_vect(a, b): return [x-y for x, y in zip(a, b)] 13 | def minus_vect(a): return [-x for x in a] 14 | 15 | def dist_l2(a, b): return sum([(x-y)**2 for x, y in zip(a, b)])**0.5 16 | def dist_squared(a, b): return sum([(x-y)**2 for x, y in zip(a, b)]) 17 | def norm_l2(a): return sum([x**2 for x in a])**0.5 18 | def norm_l2_squared(a): return sum([x**2 for x in a]) 19 | 20 | def vect_mul(vect, c): return [x*c for x in vect] # Product of vector by a scalar 21 | def scalar_prod(v1, v2): return [x*y for x, y in zip(v1, v2)] # Scalar product of two vectors 22 | def vect_det(v1, v2): return v1[0] * v2[1] - v2[0] * v1[1] # = oriented area, for two 2d vectors 23 | 24 | # Basic geometric functions 25 | def dist_line_oriented(point, line_pt1, line_pt2): # oriented distance 26 | return vect_det(sub_vect(line_pt2, line_pt1), sub_vect(point, line_pt1))/norm_l2(sub_vect(line_pt2, line_pt1)) 27 | def proj_on_line_dist_oriented(point, line_pt1, line_pt2): # oriented distance 28 | return scalar_prod(sub_vect(line_pt2-line_pt1),sub_vect(point,line_pt1))/norm_l2(sub_vect(line_pt2, line_pt1)) 29 | def angle_between(v1, v2): return atan2(vect_det(v1, v2), scalar_prod(v1, v2)) 30 | def angle_between_3(center, v1, v2): return angle_between(sub_vect(v1, center), sub_vect(v2, center)) 31 | def rad2deg(x): return 180 * x / pi; 32 | def deg2rad(x): return pi * x / 180; -------------------------------------------------------------------------------- /snippets/cpp/algo/geometry/geo_base.cpp: -------------------------------------------------------------------------------- 1 | // Base functions for Geometry 2 | 3 | using vint = lli; // Change to lli if needed, or vfloat 4 | using vfloat = long double; 5 | struct Vect { 6 | vint x, y; 7 | vint normSquare() { return x*x + y*y; } 8 | vfloat norm() { return sqrt((vfloat)(x*x + y*y)); } 9 | }; 10 | ostream& operator<<(ostream& os, const Vect& v) { os << v.x << " " << v.y; return os; } 11 | istream& operator>>(istream& is, Vect& v) { is >> v.x >> v.y; return is; } 12 | bool operator < (const Vect& a, const Vect& b) { return a.x == b.x ? a.y < b.y : a.x < b.x; } 13 | bool operator == (const Vect& a, const Vect& b) { return a.x == b.x && a.y == b.y; } 14 | bool operator != (const Vect& a, const Vect& b) { return !(a == b); } 15 | Vect operator + (const Vect& a, const Vect& b) { return {a.x + b.x, a.y + b.y}; } 16 | Vect operator - (const Vect& a, const Vect& b) { return {a.x - b.x, a.y - b.y}; } 17 | 18 | Vect operator * (const Vect& a, vint b) { return {a.x * b, a.y * b}; } // Product by a scalar 19 | Vect operator * (vint b, const Vect& a) { return {a.x * b, a.y * b}; } 20 | vint operator * (const Vect& a, const Vect& b) { return a.x * b.x + a.y * b.y; } // Scalar product 21 | vint det(const Vect& a, const Vect& b) { return a.x * b.y - b.x * a.y; } // = oriented area 22 | 23 | // Basic geometric functions 24 | vfloat distLineOriented(const Vect& point, const Vect& lineA, const Vect& lineB) { // Oriented distance 25 | return det(lineB-lineA, point-lineA) / (lineB-lineA).norm(); 26 | } 27 | vfloat projOnLineDistOriented(const Vect& point, const Vect& lineA, const Vect& lineB) { // Oriented distance 28 | return (vfloat)((lineB-lineA) * (point-lineA)) / (lineB-lineA).norm(); 29 | } 30 | vfloat angleBtw(const Vect& v1, const Vect& v2) { return atan2(det(v1, v2), v1 * v2); } 31 | vfloat angleBtw(const Vect& center, const Vect& pt1, const Vect& pt2){return angleBtw(pt1-center, pt2-center);} 32 | vfloat rad2deg(vfloat a) { return 180 * a / PI; } vfloat deg2rad(vfloat a) { return PI * a / 180; } -------------------------------------------------------------------------------- /snippets/python/structs/str_cartesian_tree.py: -------------------------------------------------------------------------------- 1 | # In reality, this is a TREAP, because the sorting key is random 2 | CartNode = namedtuple('CartNode', ['val', 'rand', 'left', 'right', 'data']) 3 | MAX_RAND = 10**9 4 | 5 | def cart_split(tree, v): 6 | """ Returns a, b : a values < s, b values >= s """ 7 | if tree is None: 8 | return None, None 9 | elif tree.val < v: 10 | a, b = cart_split(tree.right, v) 11 | return CartNode(tree.val, tree.rand, tree.left, a, tree.data), b 12 | else: 13 | a, b = cart_split(tree.left, v) 14 | return a, CartNode(tree.val, tree.rand, b, tree.right, tree.data) 15 | 16 | def cart_merge(a, b): 17 | if a is None or b is None: 18 | return a or b 19 | if a.val > b.val: a, b = b, a 20 | if a.rand >= b.rand: return CartNode(a.val, a.rand, a.left, cart_merge(a.right, b), a.data) 21 | else: return CartNode(b.val, b.rand, cart_merge(a, b.left), b.right, b.data) 22 | 23 | def cart_insert(tree, v, data=None): 24 | a, c = cart_split(tree, v) 25 | b = CartNode(v, randint(1, MAX_RAND), None, None, data) 26 | return cart_merge(cart_merge(a, b), c) 27 | 28 | def cart_remove(tree, v): 29 | a, b = cart_split(tree, v) 30 | b, c = cart_split(b, v+1) 31 | return cart_merge(a, c) 32 | 33 | def cart_get(tree, v): 34 | if tree: 35 | if tree.val == v: return tree 36 | if tree.val < v: return cart_get(tree.right, v) 37 | return cart_get(tree.left, v) 38 | 39 | def cart_upper_bound(tree, v): 40 | if tree: 41 | if tree.val <= v: return cart_upper_bound(tree.right, v) 42 | bound = cart_upper_bound(tree.left, v) 43 | return bound if bound is not None else tree.val 44 | 45 | def cart_lower_bound(tree, v): 46 | if tree: 47 | if tree.val > v: return cart_lower_bound(tree.left, v) 48 | bound = cart_lower_bound(tree.right, v) 49 | return bound if bound is not None else tree.val 50 | 51 | def cart_in(tree, v): 52 | return bool(cart_get(tree, v)) 53 | 54 | def cart_new_tree(values): 55 | t = None 56 | for v in values: 57 | t = cart_insert(t, v) 58 | return t 59 | 60 | $0 -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/flow_max_matching/algo_flow_sparse.cpp: -------------------------------------------------------------------------------- 1 | /* Min cost Max Flow algorithm using Dijkstra on a graph represented with an adjacency list */ 2 | struct Edge { int from, to, cap, flow, reversedId; }; 3 | 4 | int nbVertices=0, nbEdges, source, puit; // Init with values 5 | int maxEdgeCapInGraph = 0; 6 | vector> flowEdges; 7 | vector lastDfs; 8 | 9 | void addVertex(int from, int to, int cap) { 10 | flowEdges.resize(max((int)flowEdges.size(), max(from+1, to+1))); 11 | flowEdges[from].emplace_back(Edge{from, to, cap, 0, (int)flowEdges[to].size()}); 12 | flowEdges[to].emplace_back(Edge{to, from, 0, 0, (int)flowEdges[from].size()-1}); 13 | maxEdgeCapInGraph = max(maxEdgeCapInGraph, cap); 14 | } 15 | 16 | int maxFlowCanPush(int pos, int minCap, int minOnPath, int dfsId) { 17 | if (pos == puit) return minOnPath; 18 | if (lastDfs[pos] == dfsId) return 0; 19 | lastDfs[pos] = dfsId; 20 | for (Edge& e : flowEdges[pos]) { 21 | if (e.cap - e.flow >= minCap) { 22 | int flow = maxFlowCanPush(e.to, minCap, min(minOnPath, e.cap-e.flow), dfsId); 23 | if (flow) { 24 | e.flow += flow; 25 | flowEdges[e.to][e.reversedId].flow -= flow; 26 | return flow; 27 | } 28 | } 29 | } 30 | return 0; 31 | } 32 | 33 | int getMaxFlow() { // return {minCost, maxFlow} 34 | nbVertices = max(nbVertices, (int)flowEdges.size()); 35 | flowEdges.resize(nbVertices); lastDfs.resize(nbVertices, -1); 36 | 37 | int dfsId = 0, maxFlow = 0, pushFlow = 1; 38 | while (pushFlow * 2 <= maxEdgeCapInGraph) { pushFlow *= 2; } 39 | 40 | while (pushFlow) { 41 | int pushed = maxFlowCanPush(source, pushFlow, INF, dfsId++); 42 | if (pushed) maxFlow += pushed; 43 | else pushFlow /= 2; 44 | } 45 | return maxFlow; 46 | } 47 | 48 | // void readMaxFlow() { 49 | // cin >> nbVertices >> nbEdges >> source >> puit; 50 | 51 | // for (int iEdge = 0; iEdge < nbEdges; iEdge++) { 52 | // int vertex1, vertex2, capVertex; 53 | // cin >> vertex1 >> vertex2 >> capVertex; 54 | 55 | // addVertex(vertex1, vertex2, capVertex); 56 | // } 57 | // } -------------------------------------------------------------------------------- /snippets/cpp/utility/cout_anything.cpp: -------------------------------------------------------------------------------- 1 | template ostream& operator<<(ostream& os, const vector& v); 2 | template ostream& operator<<(ostream& os, const deque& v); 3 | template ostream& operator<<(ostream& os, const array& v); 4 | template ostream& operator<<(ostream& os, const set& v); 5 | template ostream& operator<<(ostream& os, const map& v); 6 | template ostream& operator<<(ostream& os, const unordered_set& v); 7 | template ostream& operator<<(ostream& os, const unordered_map& v); 8 | template ostream& operator<<(ostream& os, const pair& el); 9 | 10 | template ostream& operator<<(ostream& os, const vector& v) { os << "[ "; for (auto& el : v) { os << el << ", "; } os << "]"; return os; } 11 | template ostream& operator<<(ostream& os, const deque& v) { os << "[ "; for (auto& el : v) { os << el << ", "; } os << "]"; return os; } 12 | template ostream& operator<<(ostream& os, const array& v) { os << "[ "; for (auto& el : v) { os << el << ", "; } os << "]"; return os; } 13 | template ostream& operator<<(ostream& os, const set& v) { os << "( "; for (auto& el : v) { os << el << ", "; } os << ")"; return os; } 14 | template ostream& operator<<(ostream& os, const map& v) { os << "{ "; for (auto& el : v) { os << el.first << ": " << el.second << ", "; } os << "}"; return os; } 15 | template ostream& operator<<(ostream& os, const unordered_set& v) { os << "( "; for (auto& el : v) { os << el << ", "; } os << ")"; return os; } 16 | template ostream& operator<<(ostream& os, const unordered_map& v) { os << "{ "; for (auto& el : v) { os << el.first << ": " << el.second << ", "; } os << "}"; return os; } 17 | template ostream& operator<<(ostream& os, const pair& el) { os << "(" << el.first << ", " << el.second << ")"; return os; } 18 | template ostream& operator<<(ostream& os, const Matrix& v) { os << "["; for (auto& el : v) { os << "\n " << el << " ;"; } os << "\n]"; return os; } 19 | 20 | $0 -------------------------------------------------------------------------------- /snippets/python/structs/str_segtree.py: -------------------------------------------------------------------------------- 1 | class SegTree: 2 | def __init__(self, size): 3 | self.size = size 4 | self.real_size = 1 5 | while self.real_size < size: 6 | self.real_size *= 2 7 | 8 | # 9 | self.val = [0 for _ in range(self.real_size*2)] # Values of leaves and intervals 10 | self.val_propagate = [0 for _ in range(self.real_size*2)] # Lazy propagation 11 | 12 | def get_leaf(self, leaf_id): 13 | return self.val[self.real_size + leaf_id] 14 | 15 | def propagate(self, node_id): 16 | if node_id < self.real_size: 17 | pass # 18 | 19 | def update_val_interval(self, cur_node_id, val_update, target_left, target_right, sub_left=None, sub_right=None): 20 | sub_left, sub_right = sub_left or 0, sub_right or self.real_size 21 | self.propagate(cur_node_id) 22 | 23 | if target_right <= sub_left or target_left >= sub_right: # No intersection 24 | return 25 | elif target_left <= sub_left and sub_right <= target_right: # Inside of target 26 | self.val_propagate[cur_node_id] += val_update # 27 | else: 28 | mid = (sub_left + sub_right) // 2 29 | self.update_val_interval(cur_node_id * 2, val_update, target_left, target_right, sub_left, mid) 30 | self.update_val_interval(cur_node_id * 2 + 1, val_update, target_left, target_right, mid, sub_right) 31 | 32 | def request_interval(self, cur_node_id, target_left, target_right, sub_left=None, sub_right=None): 33 | sub_left, sub_right = sub_left or 0, sub_right or self.real_size 34 | self.propagate(cur_node_id) 35 | 36 | if target_right <= sub_left or target_left >= sub_right: # No intersection 37 | return 0 # 38 | elif target_left <= sub_left and sub_right <= target_right: # Inside of target 39 | return self.val[cur_node_id] # 40 | else: 41 | mid = (sub_left + sub_right) // 2 42 | v1 = self.request_interval(cur_node_id * 2, target_left, target_right, sub_left, mid) 43 | v2 = self.request_interval(cur_node_id * 2 + 1, target_left, target_right, mid, sub_right) 44 | return v1 + v2 # -------------------------------------------------------------------------------- /snippets/cpp/utility/includes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define pb push_back 5 | #define mp make_pair 6 | 7 | using lli = long long int; 8 | using ulli = unsigned long long int; 9 | using ld = long double; 10 | template using heap = priority_queue,greater >; 11 | template using hmap = unordered_map; 12 | template using hset = unordered_set; 13 | template struct Matrix : public vector> {Matrix(int dim1=0, int dim2=0, T v=T()) : vector>(dim1, vector(dim2, v)) {}}; 14 | 15 | namespace std {template struct hash> { size_t operator() (vector const& v) const { 16 | size_t c = v.size();for(auto& e : v) { c ^= (size_t)e + 0x9e3779b9 + (c << 6) + (c >> 2); }return c;}};} 17 | 18 | const int INF = 1e9; 19 | const lli LLINF = 4*1e18; 20 | const lli MOD = 1e9+7; 21 | const ld PI = 3.141592653589793; 22 | 23 | // sz, carr, minset, maxset, modul, sum 24 | template inline T sqr(T val) {return val * val;} 25 | templateinline void minset(T& a,T b){if(b < a)a=b;}templateinline void maxset(T& a,T b){if(a T modul(T val, T __modulo = MOD) {return (val%__modulo+__modulo)%__modulo;} 27 | template typename V::value_type sum(const V& els){auto s=0;for (const auto& e : els){s+=e;};return s;} 28 | template typename V::value_type min(const V& els){return *min_element(els.begin(), els.end());} 29 | template typename V::value_type max(const V& els){return *max_element(els.begin(), els.end());} 30 | struct __RM_UNUSED{__RM_UNUSED(){(void)INF; (void)LLINF; (void)PI;}};// Disable warning for unused consts 31 | 32 | string tostr(char c) { return string(1, c); } template string tostr(T c) { return to_string(c); } 33 | int toint(char c) {return c-'0';} int toint(string s, int base=10) { return stoi(s,0,base); } // stoi, stol, stoll 34 | 35 | template inline T readget(){T v;cin>>v;return v;} 36 | template ::value>::type* = nullptr > 37 | istream& operator>>(istream& is,T& v){for(auto& e:v){is>>e;}return is;} 38 | auto rng = std::default_random_engine {}; 39 | // ----------------------------------------------------------- 40 | 41 | $0 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C++ Snippets for Competitive Programming 2 | 3 | Theses snippets are aimed essentialy for competitive programming. The generators currently generate snippets for Sublime Text 3, and Visual Studio Code. 4 | 5 | The snippet [cheatsheet can be found here](snippets.md). 6 | 7 | ## Usage 8 | 9 | Snippets must first be generated, and then added to your editor. 10 | 11 | To generate all snippets, type: 12 | 13 | ```bash 14 | ./genAll.sh 15 | ``` 16 | 17 | The documenation will be generated in the file [doc.md](doc.md) 18 | 19 | ## Generated Code Snippets 20 | 21 | - Sublime text snippets location: `generated/sublimeTextSnippets` 22 | - Visual Studio Code snippets location: `generated/vscodeSnippets/competitive_snippets.code-snippets` 23 | 24 | ### How to include in your editor 25 | 26 | #### For Sublime Text 3 27 | Because snippets can be placed in subfolders, you have to put a symbolic link from your Sublime Text snippets directory (you can find it by trying to create a new snippet under Tools > Developer > New snippet, and trying to save. The prompted window should be located at this place). You can also just copy the folder, but do not forget to do this every time you update theses snippets. 28 | 29 | #### For VS Code 30 | You have to copy the file located at `generated/vscodeSnippets/competitive_snippets.code-snippets` in your User snippets directory. To do this automaticly, your can set the environment variable `$VSCODE_SNIPPETS`. It must contain the path to the snippets folder. The script `./mvCodeSnippets.sh` will move them automaticly. This script is always called after executing `./genAll.sh`. 31 | 32 | ## Snippets files format 33 | 34 | Snippets files must contain C++ code and comments. The code of file will be the snippet itself, aside from the lines starting with `//@`. 35 | 36 | ### Names and category of a snippet 37 | 38 | The name and category of snippet are set by the name of the file and the path to the file. The subfolders of the `snippets` folder within a snippet file is found will be its categories. The name of the snippet will be the filename without the `.cpp` extension. This name will also be the prefix you must type into your code editor to insert this snippet. 39 | 40 | ### Meta informations 41 | 42 | Lines starting with `//@` will be considered as meta informations and will not be included in the snippet code. These lines will have a property name and a value, following this format: 43 | ```cpp 44 | //@name This is the value of the property 45 | ``` 46 | 47 | For example: 48 | ```cpp 49 | //@doc This is a documentation line 50 | ``` 51 | 52 | Available property names: 53 | - **title**: A name for the snippet. 54 | - **doc**: Documentation for the snippet. 55 | - **defines**: List of functions / objects defined by this snippet. 56 | - **include**: include another snippet code into this snippet. 57 | 58 | You can also add a blank line that won't be included into the snippet code by typing: 59 | ```cpp 60 | //@ 61 | ``` 62 | This line will just be ignored. -------------------------------------------------------------------------------- /snippets/python/algo/flows/algo_min_cost_max_flow.py: -------------------------------------------------------------------------------- 1 | def min_cost_max_flow_init_bellman_ford(flow_edges, sources): 2 | dist_min = {vertex: LLINF for vertex in flow_edges} 3 | dist_min.update({s: 0 for s in sources}) 4 | for step in range(len(flow_edges)-1): 5 | for vertex, v_edges in flow_edges.items(): 6 | if dist_min[vertex] != LLINF: 7 | for e_to, e_cost, e_flow, e_cap, e_rev_id in v_edges: 8 | dist_min[e_to] = min(dist_min[e_to], dist_min[vertex] + e_cost) 9 | return dist_min 10 | 11 | def dijkstra_find_flow_paths(flow_edges, potential, sources, sinks): 12 | dist_min = {vertex: LLINF for vertex in flow_edges} 13 | dist_min.update({s: 0 for s in sources}) 14 | dij_prev = {v: None for v in flow_edges} 15 | 16 | sits = [(s, 0) for s in sources] 17 | heapq.heapify(sits) 18 | while sits: # Dijkstra 19 | vertex, time = heapq.heappop(sits) 20 | if time == dist_min[vertex]: 21 | for i_edge, (e_to, e_cost, e_flow, e_cap, e_rev_id) in enumerate(flow_edges[vertex]): 22 | t2 = time + e_cost + potential[vertex] - potential[e_to] 23 | if e_cap > e_flow and t2 < dist_min[e_to]: 24 | dij_prev[e_to] = (vertex, i_edge) 25 | dist_min[e_to] = t2 26 | heapq.heappush(sits, (e_to, t2)) 27 | return any(dist_min[s] != LLINF for s in sinks), dist_min, dij_prev 28 | 29 | def min_cost_max_flow_of_graph(edges, sources, sinks): 30 | """ This implementation of min-cos max-flow works with positive AND negative costs, but no negative cycle """ 31 | # Edges should be a list of [from, to, flow_cap, cost] 32 | if len(sources) > 5: 33 | sources = set(sources) 34 | # flow_edges: [from: (to, cost, flow, cap, reverse_id)] 35 | flow_edges = {v: [] for v, _, _, _ in edges} 36 | flow_edges.update({v: [] for _, v, _, _ in edges}) 37 | 38 | for e_from, e_to, e_cap, e_cost in edges: 39 | id_from, id_to = len(flow_edges[e_from]), len(flow_edges[e_to]) 40 | flow_edges[e_from].append([e_to, e_cost, 0, e_cap, id_to]) 41 | flow_edges[e_to].append([e_from, -e_cost, 0, 0, id_from]) 42 | 43 | potential = min_cost_max_flow_init_bellman_ford(flow_edges, sources) 44 | min_cost, max_flow = 0, 0 45 | while True: 46 | can_push_dij, dist_min, dij_prev = dijkstra_find_flow_paths(flow_edges, potential, sources, sinks) 47 | if not can_push_dij: 48 | break 49 | for v in flow_edges: 50 | potential[v] += dist_min[v] 51 | 52 | path = [([s for s in sinks if dist_min[s] != LLINF][0], None)] 53 | while path[-1][0] not in sources: 54 | path.append(dij_prev[path[-1][0]]) 55 | path = path[1:][::-1] # Remove the sink node as we don't need it 56 | 57 | delta = min([flow_edges[e_from][e_id][3] - flow_edges[e_from][e_id][2] for e_from, e_id in path]) 58 | for e_from, e_id in path: 59 | e_to, e_cost, e_flow, e_cap, e_rev_id = flow_edges[e_from][e_id] 60 | flow_edges[e_from][e_id][2] += delta # 2 = e_flow 61 | flow_edges[e_to][e_rev_id][2] -= delta # 2 = e_flow 62 | min_cost += delta * e_cost 63 | max_flow += delta 64 | 65 | return min_cost, max_flow, flow_edges -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/flow_max_matching/algo_min_cost_max_flow_sparse.cpp: -------------------------------------------------------------------------------- 1 | /* Min cost Max Flow algorithm using Dijkstra on a graph represented with an adjacency list */ 2 | struct Edge { int from, to, cap, cost, flow, reversedId; }; 3 | 4 | int nbVertices=0, nbEdges, source, puit; // Init with values 5 | vector> flowEdges; 6 | 7 | void addVertex(int from, int to, int cap, int cost) { 8 | flowEdges.resize(max((int)flowEdges.size(), max(from+1, to+1))); 9 | flowEdges[from].emplace_back(Edge{from, to, cap, cost, 0, (int)flowEdges[to].size()}); 10 | flowEdges[to].emplace_back(Edge{to, from, 0, -cost, 0, (int)flowEdges[from].size()-1}); 11 | } 12 | 13 | // Used internally by the algorithm 14 | vector potential, distMin; 15 | vector dijPrev; 16 | 17 | struct FlowSit { int pos, time; }; 18 | bool operator < (const FlowSit& a, const FlowSit& b) { 19 | return a.time > b.time; 20 | } 21 | 22 | bool canPushDijPath() { 23 | fill(distMin.begin(), distMin.end(), INF); 24 | distMin[source] = 0; 25 | 26 | priority_queue sits; 27 | sits.push({source, 0}); 28 | while (!sits.empty()) { // Dijkstra 29 | int pos = sits.top().pos, time = sits.top().time; 30 | sits.pop(); 31 | if (time == distMin[pos]) { 32 | for (int iEdge = 0; iEdge < (int)flowEdges[pos].size(); iEdge++) { 33 | Edge& e = flowEdges[pos][iEdge]; 34 | if (e.cap - e.flow) { 35 | int t2 = time + e.cost + potential[e.from] - potential[e.to]; 36 | if (t2 < distMin[e.to]) { 37 | dijPrev[e.to] = &flowEdges[pos][iEdge]; 38 | distMin[e.to] = t2; 39 | sits.push({e.to, t2}); 40 | } 41 | } 42 | } 43 | } 44 | } 45 | return distMin[puit] != INF; 46 | } 47 | 48 | pair getMinCostMaxFlow() { // return {minCost, maxFlow} 49 | nbVertices = max(nbVertices, (int)flowEdges.size()); 50 | potential.resize(nbVertices, 0); distMin.resize(nbVertices); 51 | flowEdges.resize(nbVertices); dijPrev.resize(nbVertices, nullptr); 52 | 53 | int minCost = 0, maxFlow = 0; 54 | while (canPushDijPath()) { 55 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 56 | potential[iVertex] += distMin[iVertex]; 57 | } 58 | int delta = INF; 59 | for (int iVertex = puit; iVertex != source; iVertex = dijPrev[iVertex]->from) { 60 | delta = min(delta, dijPrev[iVertex]->cap - dijPrev[iVertex]->flow); 61 | } 62 | for (int iVertex = puit; iVertex != source; iVertex = dijPrev[iVertex]->from) { 63 | dijPrev[iVertex]->flow += delta; 64 | flowEdges[iVertex][dijPrev[iVertex]->reversedId].flow -= delta; 65 | minCost += delta * dijPrev[iVertex]->cost; 66 | } 67 | maxFlow += delta; 68 | } 69 | return {minCost, maxFlow}; 70 | } 71 | 72 | // void readMinCostFlow() { 73 | // cin >> nbVertices >> nbEdges >> source >> puit; 74 | 75 | // for (int iEdge = 0; iEdge < nbEdges; iEdge++) { 76 | // int vertex1, vertex2, capVertex, costVertex; 77 | // cin >> vertex1 >> vertex2 >> capVertex >> costVertex; 78 | 79 | // addVertex(vertex1, vertex2, capVertex, costVertex); 80 | // } 81 | // } -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/flow_max_matching/algo_min_cost_max_flow.cpp: -------------------------------------------------------------------------------- 1 | /* Min cost Max Flow algorithm using Dijkstra. Weights must be positive */ 2 | #define MAX_VERTICES 300 3 | 4 | int nbVertices, nbEdges, source, puit; // Init with values 5 | 6 | int cap[MAX_VERTICES][MAX_VERTICES]; // Init at 0 or cap 7 | int cost[MAX_VERTICES][MAX_VERTICES]; // Init at cost 8 | int flowOnEdge[MAX_VERTICES][MAX_VERTICES]; // Set by the algorithm 9 | 10 | // Used internally by the algorithm 11 | vector vertexVois[MAX_VERTICES]; // Improve performances if the graph is sparse 12 | int potential[MAX_VERTICES], distMin[MAX_VERTICES], dijPrev[MAX_VERTICES]; 13 | 14 | struct FlowSit { int pos, time; }; 15 | bool operator < (const FlowSit& a, const FlowSit& b) { 16 | return a.time > b.time; 17 | } 18 | 19 | inline const pair getEdgeCapCost(const int a, const int b) { 20 | if (flowOnEdge[b][a] > 0) { 21 | return {flowOnEdge[b][a], - cost[b][a] + potential[a] - potential[b]}; 22 | } 23 | return {cap[a][b] - flowOnEdge[a][b], cost[a][b] + potential[a] - potential[b]}; 24 | } 25 | inline int updateAndCost(const int a, const int b, const int delta) { 26 | if (flowOnEdge[b][a] > 0) { 27 | flowOnEdge[b][a] -= delta; 28 | return - delta * cost[b][a]; 29 | } 30 | flowOnEdge[a][b] += delta; 31 | return delta * cost[a][b]; 32 | } 33 | 34 | bool canPushDijPath() { 35 | fill(distMin, distMin+MAX_VERTICES, INF); 36 | distMin[source] = 0; 37 | 38 | priority_queue sits; 39 | sits.push({source, 0}); 40 | while (!sits.empty()) { // Dijkstra 41 | int pos = sits.top().pos, time = sits.top().time; 42 | sits.pop(); 43 | if (time == distMin[pos]) { 44 | for (int v : vertexVois[pos]) { 45 | auto capCost = getEdgeCapCost(pos, v); 46 | if (capCost.first) { 47 | int t2 = time + capCost.second; 48 | if (t2 < distMin[v]) { 49 | dijPrev[v] = pos; 50 | distMin[v] = t2; 51 | sits.push({v, t2}); 52 | } 53 | } 54 | } 55 | } 56 | } 57 | return distMin[puit] != INF; 58 | } 59 | 60 | pair getMinCostMaxFlow() { // return {minCost, maxFlow} 61 | fill(flowOnEdge[0], flowOnEdge[0]+MAX_VERTICES*MAX_VERTICES, 0); 62 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 63 | for (int iVois = 0; iVois < nbVertices; iVois++) { 64 | if (cap[iVertex][iVois] != 0 || cap[iVois][iVertex] != 0) { 65 | vertexVois[iVertex].emplace_back(iVois); 66 | } 67 | } 68 | } 69 | int minCost = 0, maxFlow = 0; 70 | while (canPushDijPath()) { 71 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 72 | potential[iVertex] += distMin[iVertex]; 73 | } 74 | int delta = INF; 75 | for (int iVertex = puit; iVertex != source; iVertex = dijPrev[iVertex]) { 76 | auto capCost = getEdgeCapCost(dijPrev[iVertex], iVertex); 77 | delta = min(delta, capCost.first); 78 | } 79 | for (int iVertex = puit; iVertex != source; iVertex = dijPrev[iVertex]) { 80 | minCost += updateAndCost(dijPrev[iVertex], iVertex, delta); 81 | } 82 | maxFlow += delta; 83 | } 84 | return {minCost, maxFlow}; 85 | } -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/flow_max_matching/algo_min_cost_max_flow_negative.cpp: -------------------------------------------------------------------------------- 1 | /* Min cost Max Flow algorithm using Dijkstra and bellman-ford. Works with negative weights */ 2 | struct Edge { int from, to, cap, cost, flow, reversedId; }; 3 | 4 | int nbVertices=0, nbEdges, source, puit; // Init with values 5 | vector> flowEdges; 6 | 7 | void addVertex(int from, int to, int cap, int cost) { 8 | flowEdges.resize(max((int)flowEdges.size(), max(from+1, to+1))); 9 | flowEdges[from].emplace_back(Edge{from, to, cap, cost, 0, (int)flowEdges[to].size()}); 10 | flowEdges[to].emplace_back(Edge{to, from, 0, -cost, 0, (int)flowEdges[from].size()-1}); 11 | } 12 | 13 | // Used internally by the algorithm 14 | vector potential, distMin; 15 | vector dijPrev; 16 | 17 | struct FlowSit { int pos, time; }; 18 | bool operator < (const FlowSit& a, const FlowSit& b) { 19 | return a.time > b.time; 20 | } 21 | 22 | void initWithBellmanFord() { 23 | fill(distMin.begin(), distMin.end(), INF); 24 | distMin[source] = 0; 25 | for (int step = 0; step < nbVertices-1; step++) { 26 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 27 | if (distMin[iVertex] != INF) { 28 | for (Edge& e : flowEdges[iVertex]) { 29 | distMin[e.to] = min(distMin[e.to], distMin[iVertex] + e.cost); 30 | } 31 | } 32 | } 33 | } 34 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 35 | potential[iVertex] = distMin[iVertex]; 36 | } 37 | } 38 | 39 | bool canPushDijPath() { 40 | fill(distMin.begin(), distMin.end(), INF); 41 | distMin[source] = 0; 42 | 43 | priority_queue sits; 44 | sits.push({source, 0}); 45 | while (!sits.empty()) { // Dijkstra 46 | int pos = sits.top().pos, time = sits.top().time; 47 | sits.pop(); 48 | if (time == distMin[pos]) { 49 | for (int iEdge = 0; iEdge < (int)flowEdges[pos].size(); iEdge++) { 50 | Edge& e = flowEdges[pos][iEdge]; 51 | if (e.cap - e.flow) { 52 | int t2 = time + e.cost + potential[e.from] - potential[e.to]; 53 | if (t2 < distMin[e.to]) { 54 | dijPrev[e.to] = &flowEdges[pos][iEdge]; 55 | distMin[e.to] = t2; 56 | sits.push({e.to, t2}); 57 | } 58 | } 59 | } 60 | } 61 | } 62 | return distMin[puit] != INF; 63 | } 64 | 65 | pair getMinCostMaxFlow() { // return {minCost, maxFlow} 66 | nbVertices = max(nbVertices, (int)flowEdges.size()); 67 | potential.resize(nbVertices, 0); distMin.resize(nbVertices); 68 | flowEdges.resize(nbVertices); dijPrev.resize(nbVertices, nullptr); 69 | 70 | int minCost = 0, maxFlow = 0; 71 | initWithBellmanFord(); 72 | while (canPushDijPath()) { 73 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 74 | potential[iVertex] += distMin[iVertex]; 75 | } 76 | int delta = INF; 77 | for (int iVertex = puit; iVertex != source; iVertex = dijPrev[iVertex]->from) { 78 | delta = min(delta, dijPrev[iVertex]->cap - dijPrev[iVertex]->flow); 79 | } 80 | for (int iVertex = puit; iVertex != source; iVertex = dijPrev[iVertex]->from) { 81 | dijPrev[iVertex]->flow += delta; 82 | flowEdges[iVertex][dijPrev[iVertex]->reversedId].flow -= delta; 83 | minCost += delta * dijPrev[iVertex]->cost; 84 | } 85 | maxFlow += delta; 86 | } 87 | return {minCost, maxFlow}; 88 | } 89 | 90 | // void readMinCostFlow() { 91 | // cin >> nbVertices >> nbEdges >> source >> puit; 92 | 93 | // for (int iEdge = 0; iEdge < nbEdges; iEdge++) { 94 | // int vertex1, vertex2, capVertex, costVertex; 95 | // cin >> vertex1 >> vertex2 >> capVertex >> costVertex; 96 | 97 | // addVertex(vertex1, vertex2, capVertex, costVertex); 98 | // } 99 | // } -------------------------------------------------------------------------------- /snippets/cpp/structs/str_carttree.cpp: -------------------------------------------------------------------------------- 1 | // WIP 2 | 3 | template struct CartTree { // Not persistant 4 | T val; 5 | int weight; // min weight on top 6 | CartTree* left; 7 | CartTree* right; 8 | int _size; 9 | bool reverse; 10 | 11 | CartTree(T value) : val(value), left(nullptr), right(nullptr), _size(1), reverse(false) { weight = rand(); } 12 | pair split(T splitVal, bool includeVal=false) { 13 | // tree1 < splitVal <= tree2 if includeVal=false, tree1 <= splitVal < tree2 otherwise 14 | this->propagNode(); 15 | if (val < splitVal || (includeVal && !(splitVal < val))) { 16 | CartTree* right2 = nullptr; 17 | if (right != nullptr) { 18 | auto p = right->split(splitVal, includeVal); 19 | right = p.first; 20 | right2 = p.second; 21 | } 22 | this->updateNode(); 23 | return {this, right2}; 24 | } 25 | CartTree* left1 = nullptr; 26 | if (left != nullptr) { 27 | auto p = left->split(splitVal, includeVal); 28 | left1 = p.first; 29 | left = p.second; 30 | } 31 | this->updateNode(); 32 | return {left1, this}; 33 | } 34 | ~CartTree() { delete left; delete right; } 35 | inline int size() const {return this->_size;} 36 | 37 | static CartTree* merge(CartTree* a, CartTree* b) { 38 | if (a == nullptr) { return b; } if (b == nullptr) { return a; } 39 | if (a->weight < b->weight) { 40 | a->propagNode(); 41 | a->right = CartTree::merge(a->right, b); 42 | a->updateNode(); 43 | return a; 44 | } 45 | b->propagNode(); 46 | b->left = CartTree::merge(a, b->left); 47 | b->updateNode(); 48 | return b; 49 | } 50 | CartTree* mergeLeft(CartTree* a) {return CartTree::merge(a, this); } 51 | CartTree* mergeRight(CartTree* b) {return CartTree::merge(this, b); } 52 | 53 | void propagNode() { 54 | if (reverse) { 55 | reverse=false; 56 | if (left!=nullptr) { left->reverse = !left->reverse; } 57 | if (right!=nullptr) { right->reverse = !right->reverse; } 58 | } 59 | } 60 | void updateNode() { 61 | // Overwrides must start with CartTree::updateNode(); 62 | this->_size = 1 + (left==nullptr?0:left->_size) + (right==nullptr?0:right->_size); 63 | this->propagNode(); 64 | } 65 | 66 | inline static int empty(CartTree* a) {return a!=nullptr;} 67 | inline static int size(CartTree* a) {return a==nullptr?0:a->size();} 68 | 69 | CartTree* insert(CartTree* node) { 70 | auto p = this->split(node->val); 71 | return node->mergeLeft(p.first)->mergeRight(p.second); 72 | } 73 | CartTree* insert(T value) { return this->insert(new CartTree(value)); } 74 | static CartTree* insert(CartTree* tree, T value) {return tree==nullptr?new CartTree(value):tree->insert(value);} 75 | CartTree* remove(T value) { // Remove all nodes with this value 76 | auto p1 = this->split(value); 77 | auto p2 = p1.second->split(value); 78 | delete p2.first; 79 | return p1.first->mergeRight(p2.second); 80 | } 81 | 82 | T& getNthValue(int n) { 83 | int leftSize = CartTree::size(left); 84 | if (leftSize > n) { 85 | return left->getNthValue(n); 86 | } else if (leftSize == n) { 87 | return val; 88 | } 89 | if (right == nullptr) { 90 | cerr << "Error CartTree getNthValue\n"; 91 | } 92 | return right->getNthValue(n-leftSize-1); 93 | } 94 | };// Usage : CartTree* t = nullptr; and then build 95 | // using Tree = CartTree; // Tree* t = nullptr; 96 | template ostream& operator<<(ostream& os, const CartTree* t) { 97 | if (t != nullptr) { 98 | os << "[" << t->left << "] - "; 99 | os << "(" << t->val << " ; size=" << t->_size << ")"; 100 | os << " - [" << t->right << "]"; 101 | } return os; 102 | } -------------------------------------------------------------------------------- /scripts/utils.py: -------------------------------------------------------------------------------- 1 | import os, copy, sys 2 | 3 | AVAILABLE_PROPERTIES = ["title", "doc", "defines", "include"] # '//@' will be ignorer 4 | SNIPPETS_ROOT = "snippets" 5 | 6 | def getSnippetsFiles(): 7 | """ 8 | Return all the snippet files as a list of 9 | { 10 | 'filepath': , 11 | 'name': , 12 | 'dirpath': , 13 | } 14 | """ 15 | files = [] 16 | for (dirpath, dirnames, filenames) in os.walk(SNIPPETS_ROOT): 17 | newDir = "/".join([SNIPPETS_ROOT]+dirpath.split("/")[1:]) 18 | os.makedirs(newDir, exist_ok=True) 19 | 20 | for fName in filenames: 21 | if os.path.splitext(fName)[1] in ['.cpp', '.py']: 22 | fileInfos = { 23 | 'filepath': os.path.join(dirpath, fName), 24 | 'name': os.path.splitext(fName)[0], 25 | 'dirpath': os.path.join(*(dirpath.split(os.path.sep)[1:])), 26 | 'category': list(dirpath.split(os.path.sep)[1:]), 27 | 'lang': os.path.splitext(fName)[1][1:] 28 | } 29 | files.append(fileInfos) 30 | return files 31 | 32 | def insertInTemplate(templatePath, blocks): 33 | with open(templatePath, "r") as f: 34 | template = "".join(f.readlines()) 35 | for name, content in blocks.items(): 36 | seq = "{{{" + name + "}}}" 37 | template = template.replace(seq, content) 38 | return template 39 | 40 | def removeFileComment(fileLines): 41 | return [l for l in fileLines if l[:1] != "@" and l[:3] != "/*@"] 42 | 43 | def getIncludedSnippet(snippetName): 44 | """ 45 | Return the code of a given snippet. 46 | The name must be in a format like : algo/maths/math_numeric , without the ".cpp" extension. 47 | """ 48 | fileInfos = { 49 | 'filepath': os.path.join(SNIPPETS_ROOT, snippetName), 50 | 'name': '', 'dirpath': '', 'category': '', 'lang': '' 51 | } 52 | try: 53 | return readSnippet(fileInfos)["code"] 54 | except FileNotFoundError: 55 | sys.stderr.write("ERROR : {} doesn't exist\n".format(snippetName)) 56 | return [] 57 | 58 | def readSnippet(fileInfos): 59 | properties = { 60 | prop : [] for prop in AVAILABLE_PROPERTIES 61 | } 62 | 63 | with open(fileInfos['filepath'], "r") as snippet: 64 | lines = [l.rstrip() for l in snippet.readlines()] 65 | metaLines = [l[3:].strip() for l in lines if l[:3] == "//@"] 66 | cppLines = [l for l in lines if l[:3] != "//@"] 67 | 68 | metaLines = [l for l in metaLines if l] 69 | metaProps = [l.split()[0].strip() for l in metaLines] 70 | metaDatas = [ 71 | (prop, val[len(prop):].strip()) for prop, val in zip(metaProps, metaLines) 72 | ] 73 | 74 | for (prop, val) in metaDatas: 75 | if not prop in properties: 76 | raise Exception("Unknown property: {}".format(prop)) 77 | properties[prop].append(val) 78 | 79 | includedLines = [] 80 | for included in properties["include"]: 81 | includedLines += getIncludedSnippet(included) 82 | 83 | return { 84 | 'name': fileInfos["name"], 85 | 'properties': properties, 86 | 'code': includedLines + cppLines, 87 | 'dirpath': fileInfos["dirpath"], 88 | 'category': fileInfos["category"], 89 | 'lang': fileInfos["lang"], 90 | } 91 | 92 | def getAllSnippets(): 93 | return [readSnippet(fileInfos) for fileInfos in getSnippetsFiles()] 94 | 95 | def addSnippetToTree(tree, snippet, category, level): 96 | tree["_level_"] = level 97 | if not "_contain_" in tree: 98 | tree["_contain_"] = [] 99 | if category == []: 100 | tree["_contain_"].append(snippet) 101 | else: 102 | if not category[0] in tree: 103 | tree[category[0]] = {} 104 | addSnippetToTree(tree[category[0]], snippet, category[1:], level+1) 105 | 106 | def getSnippetsTree(snippetsDatas): 107 | tree = {} 108 | for snippet in snippetsDatas: 109 | addSnippetToTree(tree, snippet, snippet["category"], 0) 110 | return tree -------------------------------------------------------------------------------- /snippets/cpp/algo/graphs/flow_max_matching/algo_min_cost_max_flow_slower.cpp: -------------------------------------------------------------------------------- 1 | //@defines getMinCostMaxFlow 2 | //@ 3 | #define MAX_VERTICES 1000 4 | 5 | int cap[MAX_VERTICES][MAX_VERTICES]; 6 | int cost[MAX_VERTICES][MAX_VERTICES]; 7 | int flowOnEdge[MAX_VERTICES][MAX_VERTICES]; 8 | 9 | vector vertexVois[MAX_VERTICES]; 10 | int flowDijNext[MAX_VERTICES], flowDijDepth[MAX_VERTICES]; 11 | int label[MAX_VERTICES]; 12 | 13 | int nbVertices, nbEdges, source, puit; 14 | 15 | inline int edgeCost(const int from, const int to) { 16 | return flowDijDepth[from] + label[from] - label[to]; 17 | } 18 | 19 | bool canPushWithDijkstra() { 20 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 21 | flowDijDepth[iVertex] = INF; 22 | flowDijNext[iVertex] = -1; 23 | } 24 | flowDijDepth[source] = 0; 25 | flowDijNext[source] = -nbVertices - 1; 26 | 27 | while (true) { 28 | int vertDepthMin = -1, minDepth = INF; 29 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 30 | if (flowDijNext[iVertex] < 0 && flowDijDepth[iVertex] < minDepth) { 31 | vertDepthMin = iVertex; 32 | minDepth = flowDijDepth[iVertex]; 33 | } 34 | } 35 | if (minDepth == INF) { 36 | break; 37 | } 38 | 39 | // relax edge (vertDepthMin, iVertex) or (iVertex, vertDepthMin) for all iVertex 40 | flowDijNext[vertDepthMin] = -flowDijNext[vertDepthMin] - 1; 41 | for (int iVertex : vertexVois[vertDepthMin]) { 42 | if (flowDijNext[iVertex] >= 0) { 43 | continue; 44 | } 45 | if (flowOnEdge[iVertex][vertDepthMin] && flowDijDepth[iVertex] > edgeCost(vertDepthMin, iVertex) - cost[iVertex][vertDepthMin]) { 46 | flowDijDepth[iVertex] = edgeCost(vertDepthMin, iVertex) - cost[iVertex][vertDepthMin]; 47 | flowDijNext[iVertex] = -vertDepthMin-1; 48 | } 49 | 50 | // try edge vertDepthMin->iVertex 51 | if (flowOnEdge[vertDepthMin][iVertex] < cap[vertDepthMin][iVertex] 52 | && flowDijDepth[iVertex] > edgeCost(vertDepthMin, iVertex) + cost[vertDepthMin][iVertex]) { 53 | flowDijDepth[iVertex] = edgeCost(vertDepthMin, iVertex) + cost[vertDepthMin][iVertex]; 54 | flowDijNext[iVertex] = -vertDepthMin - 1; 55 | } 56 | } 57 | } 58 | 59 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 60 | if (label[iVertex] < INF) { 61 | label[iVertex] += flowDijDepth[iVertex]; 62 | } 63 | } 64 | 65 | return flowDijNext[puit] >= 0; 66 | } 67 | 68 | pair getMinCostMaxFlow() { // return {min_cost, max_flow} 69 | fill(flowOnEdge[0], flowOnEdge[0] + MAX_VERTICES*MAX_VERTICES, 0); 70 | fill(label, label + MAX_VERTICES, 0); 71 | 72 | for (int iVertex = 0; iVertex < nbVertices; iVertex++) { 73 | for (int iNext = 0; iNext < nbVertices; iNext++) { 74 | if (cap[iVertex][iNext] || cap[iNext][iVertex]) { 75 | vertexVois[iVertex].push_back(iNext); 76 | } 77 | } 78 | } 79 | 80 | int flow = 0, flowCost = 0; 81 | 82 | while (canPushWithDijkstra()) { 83 | int capMinPath = INF; 84 | for (int iVertex = puit, iNext = flowDijNext[iVertex]; iVertex != source; iVertex = iNext, iNext = flowDijNext[iVertex]) { 85 | if (flowOnEdge[iVertex][iNext]) { 86 | capMinPath = min(capMinPath, flowOnEdge[iVertex][iNext]); 87 | } else { 88 | capMinPath = min(capMinPath, cap[iNext][iVertex] - flowOnEdge[iNext][iVertex]); 89 | } 90 | } 91 | 92 | // update the flow network 93 | for (int iVertex = puit, iNext = flowDijNext[iVertex]; iVertex != source; iVertex = iNext, iNext = flowDijNext[iVertex]) { 94 | if (flowOnEdge[iVertex][iNext]) { 95 | flowOnEdge[iVertex][iNext] -= capMinPath; 96 | flowCost -= capMinPath * cost[iVertex][iNext]; 97 | } else { 98 | flowOnEdge[iNext][iVertex] += capMinPath; 99 | flowCost += capMinPath * cost[iNext][iVertex]; 100 | } 101 | } 102 | 103 | flow += capMinPath; 104 | } 105 | 106 | return {flowCost, flow}; 107 | } 108 | 109 | -------------------------------------------------------------------------------- /snippets.md: -------------------------------------------------------------------------------- 1 | ## Code 2 | 3 | TODO : split string, fft, see ulm book 4 | 5 | - **Utility** 6 | - `includes` 7 | - `main_default` 8 | - `islocal` *(compile with -Don_local)* 9 | - `cout_anything` (for debugging purposes) 10 | - `string_utility` (`split`, `trim`, `ltrim`, `rtrim`) 11 | - `usaco` *Read and write in files* 12 | - `sync_false` 13 | - `testsfor` *(read the number of tests and loop over it)* 14 | - **C++ shortcurts** 15 | - `foru` *(itérer ascendant)* 16 | - `ford` *(itérer descendant)* 17 | - `forel` *(itérer dans une structure)* 18 | - `foriel` *(itérer indice et élément (like `enumerate` in python))* 19 | - `infop` *(opérateur < rapidement)* 20 | - `lambda` 21 | - `vv` *(`vector` par défaut)* 22 | - `ssize` *(int)___.size()* 23 | - `reresize` *resize(0) ; resize(n) *(or `.assign(n, val)`)* 24 | - `2pb` 25 | - `rint`, `rvar` 26 | - `print` *cout with spaces and newline* 27 | - **Definitions** 28 | - `def_consts` 29 | - `def_types` 30 | - **Contest-specific templates** 31 | - `battleDev_main` 32 | 33 | ## Tools 34 | 35 | - `tool_reindexer` 36 | 37 | ## Structs 38 | 39 | - `str_graph` 40 | - `str_bigint` 41 | - `str_pos` *(Pos et moves)* 42 | - `str_grid` *(Read and store grid, functions on grids)* 43 | - `str_segtree` 44 | - `segtree_template` 45 | - `segtree_max`, `segtree_sum` 46 | 47 | ## I/O 48 | - **Read functions** 49 | - `read_graph` 50 | - `read_graph_pondere` 51 | - `read_flow` 52 | - `read_min_cost_flow` 53 | - `read_max_matching` 54 | - **Data conversion** 55 | - `grid_to_flow` *// Convert grid to max flow graph* 56 | - `grid_to_graph` 57 | 58 | ## Algo 59 | 60 | - **General** 61 | - `algo_union_find` 62 | - `algo_dicho` *// Dichotomie* 63 | - `algo_merge_sort` 64 | - **Graphs** *(requires str_graph)* 65 | - `algo_contain_cycle` 66 | - `algo_dfs` 67 | - `algo_tri_topo` 68 | - **Shortest path algorithms** 69 | - `algo_bfs` 70 | - `algo_remonte_bfs` 71 | - `algo_dijkstra` 72 | - `algo_remonte_dijkstra` 73 | - `algo_bellman_ford` 74 | - `algo_floyd_warshall` 75 | - **Flows / max matching** 76 | - `algo_flow` , `algo_flow_sparse` 77 | - `algo_min_cut`, `algo_min_cut_sparse` 78 | - `algo_min_cost_max_flow` , `algo_min_cost_max_flow_sparse` , `algo_min_cost_max_flow_slower` 79 | - `algo_min_cost_max_flow_negative` // Works with negative costs 80 | - `algo_max_matching` 81 | - **Maths** 82 | - `math_usual` *// pgcd, ppcm, factorielle, base conversion 83 | - `math_primes` *// genNPrimes, genPrimesUnder* 84 | - **Geometry** 85 | - $x*y=||x||.||y||.cos(x,y)$, $det(x,y)=||x||.||y||.sin(x,y)$ 86 | - Composante colinéaire à $x$ : $\frac{x*y}{||x||}$. Orthogonale : $\frac{det(x,y)}{||x||}$ 87 | - `geo_base` (Vect and base functions. Set vint = double if you want non-integer coords) 88 | - `geo_rects` (To work with rectangles) 89 | - `geo_segs` (To work with segments and lines) 90 | - `geo_convex_hull.cpp` 91 | - `geo_shapes` // borderToSegs, arePointsInArea, ... 92 | 93 | ## C++ useful functions 94 | 95 | - `[string].substr(start, size)` *// Get a substring* 96 | - `to_string(value)` *// something to string* 97 | - `stoi(string, pos=0, base=10)` *// string to int* 98 | - Cout with 0 at the begening: ```cout.fill('0’); cout.width(4);``` 99 | - ```std::fixed``` puis ```setprecision(k)``` 100 | - `priority_queue, decltype(comp)> ` 101 | - `atan2` 102 | 103 | 104 | 105 | # Python 106 | 107 | ## Code 108 | 109 | - `main`, `mainMini` 110 | - `util_points_geo` (vectors, points as tuples, basic geometry) 111 | - `util_math` (primes, pgcd, ppcm, fact, binom, is_palindrom) 112 | - `util_collections` (with `argmin`, `argmax`, and for dicts, and uchain, l2str, `reindexer`) 113 | - `util_search` (upper_bound, lower_bound, range, is_in_sorted) 114 | - `util_combi` (next_permutation, get_permuts) 115 | - `util_sequences_str` (prefixs, suffixs) 116 | - Short names: 117 | - `cin`, `cout` 118 | - `rr`, `rint`,`rmint`, `lrmint`, `fprint` 119 | - `forr`, `foru`, `ford` 120 | - (`read_print`) 121 | - `struct` (With nammed tuple. Set with `a = a._replace(x=11, z=a.y)`) 122 | 123 | ## Structures 124 | 125 | May be required by some algorithms 126 | 127 | - `str_heap` 128 | - `str_graph` 129 | 130 | ## Algo 131 | 132 | - General 133 | - `algo_union_find` 134 | - `algo_dicho` 135 | - `algo_merge_sort` 136 | - `algo_cumul` 137 | - `algo_dicho` 138 | - `algo_cfc` 139 | - Graph 140 | - `algo_dfs` 141 | - `algo_bfs ` (BFS + path) 142 | - `algo_dij` (Dijkstra + path) 143 | - `algo_bellman_ford` 144 | - `algo_floyd_warshall` 145 | - Flows, max-matching :`algo_max_matching`, `algo_max_flow`, `algo_min_cut`, `algo_min_cost_max_flow` 146 | - `convex_hull` (Some other geometry in `util_points_geo`) 147 | - Structures 148 | - `str_cartesian_tree` (and `str_cartesian_tree_extras`) 149 | - `str_heap` 150 | - `str_graph` 151 | - `str_deque` 152 | - `str_segtree`, `str_segtree_max`, `str_segtree_sum` 153 | 154 | ## Python useful functions 155 | 156 | - `{0:.2f}'.format(x)`, `round(x, 2)` 157 | - `map(f, l)`, `filter(f, l)`, `reduce(f, l, start)` 158 | - `deque.pop()`, `deque.popleft()`, `deque.append()`, `deque.appendleft` 159 | - `dict.keys()`, `dict.items()`, `dict.pop(key)`, `dict.values()` 160 | - `set.add(v)`, `s.remove(v)` 161 | - `accumulate(list, [func, initial=None])`, `chain(list1, list2, ...)` 162 | - `permutations(list)`, `combinations(list)`, `product(list1, list2, ...)` -------------------------------------------------------------------------------- /snippets/cpp/structs/str_bigint.cpp: -------------------------------------------------------------------------------- 1 | class Bigint; 2 | Bigint abs(Bigint); 3 | std::string to_string(Bigint const &); 4 | Bigint big_factorial(int); 5 | 6 | class Bigint { public: 7 | //Constructors 8 | Bigint(); Bigint(long long); Bigint(std::string); Bigint(const Bigint& b); 9 | //Access 10 | int operator[](int const &); 11 | //Helpers 12 | void clear(); 13 | Bigint &abs(); 14 | //Power 15 | Bigint &pow(int const &); 16 | //Trivia 17 | int digits() const; 18 | int trailing_zeros() const; 19 | 20 | friend std::istream &operator>>(std::istream &, Bigint &);friend std::ostream &operator<<(std::ostream &, Bigint const &);Bigint operator+(Bigint const &) const;Bigint &operator+=(Bigint const &);Bigint operator+(long long const &) const;Bigint &operator+=(long long);Bigint operator-(Bigint const &) const;Bigint &operator-=(Bigint const &);Bigint operator*(Bigint const &);Bigint &operator*=(Bigint const &);Bigint operator*(long long const &);Bigint &operator*=(int const &);bool operator<(const Bigint &) const;bool operator>(const Bigint &) const;bool operator<=(const Bigint &) const;bool operator>=(const Bigint &) const;bool operator==(const Bigint &) const;bool operator!=(const Bigint &) const;Bigint operator=(const long long &);private:std::vector number;bool positive;int base;unsigned int skip;static const int default_base=1000000000;private:int segment_length(int) const;Bigint pow(int const &, std::map &);int compare(Bigint const &) const;};Bigint::Bigint(){positive = true;base = Bigint::default_base;skip = 0;}Bigint::Bigint(const Bigint &b) : number(b.number), positive(b.positive), base(b.base), skip(b.skip) { }Bigint::Bigint(long long value){base = Bigint::default_base;skip = 0;if (value < 0) {positive = false;value *= -1;} else {positive = true;}while (value) {number.push_back((int) (value % base));value /= base;}}Bigint::Bigint(std::string stringInteger){int size = stringInteger.length();base = Bigint::default_base;skip = 0;positive = (stringInteger[0] != '-');while (true) {if (size <= 0) break;if (!positive && size <= 1) break;int length = 0;int num = 0;int prefix = 1;for (int i(size - 1); i >= 0 && i >= size - 9; --i) {if (stringInteger[i] < '0' || stringInteger[i] > '9') break;num += (stringInteger[i] - '0') * prefix;prefix *= 10;++length;}number.push_back(num);size -= length;}}Bigint Bigint::operator+(Bigint const &b) const{Bigint c = *this;c += b;return c;}Bigint &Bigint::operator+=(Bigint const &b){if (!b.positive) {return *this -= b;}std::vector::iterator it1 = number.begin();std::vector::const_iterator it2 = b.number.begin();int sum = 0;while (it1 != number.end() || it2 != b.number.end()) {if (it1 != number.end()) {sum += *it1;} else {number.push_back(0);it1 = number.end()-1;}if (it2 != b.number.end()) {sum += *it2;++it2;}*it1 = sum % base;++it1;sum /= base;}if (sum) number.push_back(1);return *this;}Bigint Bigint::operator+(long long const &b) const{Bigint c = *this;c += b;return c;}Bigint &Bigint::operator+=(long long b){std::vector::iterator it = number.begin();if (skip > number.size()) {number.insert(number.end(), skip - number.size(), 0);}it += skip;bool initial_flag=true;while (b || initial_flag) {initial_flag=false;if (it != number.end()) {*it += b % base;b /= base;b += *it / base;*it %= base;++it;} else {number.push_back(0);it = number.end() - 1;}}return *this;}Bigint Bigint::operator-(Bigint const &b) const{Bigint c = *this;c -= b;return c;}Bigint &Bigint::operator-=(Bigint const &b){std::vector::iterator it1 = number.begin();std::vector::const_iterator it2 = b.number.begin();int dif = 0;while (it1 != number.end() || it2 != b.number.end()) {if (it1 != number.end()) {dif += *it1;++it1;}if (it2 != b.number.end()) {dif -= *it2;++it2;}if (dif < 0) {*(it1 - 1) = dif + base;dif = -1;} else {*(it1 - 1) = dif % base;dif /= base;}}if (dif < 0) positive = false;if (number.size() > 1){do{it1 = number.end() - 1;if (*it1 == 0) number.pop_back();else break;} while (number.size() > 1);}return *this;}Bigint Bigint::operator*(Bigint const &b){if (b.number.size() == 1) return *this *= b.number[0];std::vector::iterator it1;std::vector::const_iterator it2;Bigint c;for (it1 = number.begin(); it1 != number.end(); ++it1) {for (it2 = b.number.begin(); it2 != b.number.end(); ++it2) {c.skip = (unsigned int) (it1 - number.begin()) + (it2 - b.number.begin()); c += (long long) (*it1) * (*it2);}}c.skip = 0;return c;}Bigint &Bigint::operator*=(Bigint const &b){*this = *this * b;return *this;}Bigint Bigint::operator*(long long const &b){Bigint c = *this;c *= b;return c;}Bigint &Bigint::operator*=(int const &b){std::vector::iterator it = number.begin();long long sum = 0;while (it != number.end()) {sum += (long long) (*it) * b;*it = (int) (sum % base);sum /= base;++it;}if (sum) number.push_back((int) sum);return *this;}Bigint Bigint::pow(int const &power, std::map &lookup){if (power == 1) return *this;if (lookup.count(power)) return lookup[power];int closestPower = 1;while (closestPower < power) closestPower <<= 1;closestPower >>= 1;if (power == closestPower) lookup[power] = pow(power / 2, lookup) * pow(power / 2, lookup);else lookup[power] = pow(closestPower, lookup) * pow(power - closestPower, lookup);return lookup[power];}Bigint &Bigint::pow(int const &power){std::map lookup;if (power % 2 == 0 && !positive) {positive = true;}*this = pow(power, lookup);return *this;}int Bigint::compare(const Bigint &a) const {if (positive && !a.positive) return 1;if (!positive && a.positive) return -1;int check = 1;if (!positive && !a.positive) check = -1;if (number.size() < a.number.size()) return -1 * check;if (number.size() > a.number.size()) return check;for (size_t i(number.size()); i > 0; --i) {if (number[i-1] < a.number[i-1]) return -1 * check;if (number[i-1] > a.number[i-1]) return check;}return 0; }bool Bigint::operator<(Bigint const &b) const{return compare(b) == -1;}bool Bigint::operator<=(const Bigint &b) const{int compared = compare(b);return compared == 0 || compared == -1;}bool Bigint::operator>(const Bigint &b) const{return compare(b) == 1;}bool Bigint::operator>=(const Bigint &b) const{int compared = compare(b);return compared == 0 || compared == 1;}bool Bigint::operator==(Bigint const &b) const{return compare(b) == 0;}bool Bigint::operator!=(Bigint const &b) const{return ! (*this == b);}Bigint Bigint::operator=(const long long &a){number.clear();long long t = a;do {number.push_back((int) (t % base));t /= base;} while (t != 0);return *this;}int Bigint::operator[](int const &b){return to_string(*this)[b] - '0';}int Bigint::digits() const{int segments = number.size();if (segments == 0) return 0;int digits = 9 * (segments - 1);digits += segment_length(number.back());return digits;}int Bigint::trailing_zeros() const{if (number.empty() || (number.size() == 1 && number[0] == 0)) return 1;int zeros = 0;std::vector::const_iterator it = number.begin();if (number.size() > 1) {for (; it != number.end() - 1 && *it == 0; ++it) {zeros += 9;}}int a = *it;while (a % 10 == 0 && a) {++zeros;a /= 10;}return zeros;}void Bigint::clear(){number.clear();positive = true;skip = 0;}Bigint &Bigint::abs(){positive = true;return *this;}std::ostream &operator<<(std::ostream &out, Bigint const &a){if (!a.number.size()) return out << 0;int i = a.number.size() - 1;for (; i>=0 && a.number[i] == 0; --i){}if (i == -1) return out << 0;if (!a.positive) out << '-';std::vector::const_reverse_iterator it = a.number.rbegin() + (a.number.size() - i - 1);out << *it++;for (; it != a.number.rend(); ++it) {for (int ij(0), len = a.segment_length(*it); ij < 9 - len; ++ij) out << '0';if (*it) out << *it;}return out;}std::istream &operator>>(std::istream &in, Bigint &a){std::string str;in >> str;a = str;return in;}int Bigint::segment_length(int segment) const{int length = 0;while (segment) {segment /= 10;++length;}return length;}Bigint abs(Bigint value){return value.abs();}std::string to_string(Bigint const &value){std::ostringstream stream;stream << value;return stream.str();}Bigint big_factorial(int n){Bigint result = 1;if (n % 2) {result = n;--n;}int last = 0;for (; n >= 2; n -= 2) {result *= n + last;last += n;}return result;} 21 | 22 | $0 --------------------------------------------------------------------------------