├── .gitignore ├── makefile ├── manual.pdf ├── manual.tex ├── other ├── README.md ├── anuncieaqui-biblioteca │ ├── .gitignore │ ├── .hgignore │ ├── .todo │ ├── Makefile │ ├── config │ │ ├── Makefile │ │ ├── dotemacs │ │ ├── dotvimrc │ │ ├── flymake.mk │ │ ├── hashgen │ │ └── template.cpp │ ├── gen_hash.sh │ ├── geometry │ │ ├── Makefile │ │ ├── closest_points.cpp │ │ ├── enclosing_circle.cpp │ │ ├── hull.cpp │ │ ├── isect_primitives.cpp │ │ ├── kd_tree.cpp │ │ ├── misc_primitives.cpp │ │ ├── point.cpp │ │ ├── polygon_primitives.cpp │ │ └── range_tree.cpp │ ├── graph │ │ ├── Makefile │ │ ├── busacker_gowen.cpp │ │ ├── dijkstra_sparse_fast.cpp │ │ ├── dijkstra_sparse_small.cpp │ │ ├── dinic.cpp │ │ ├── edmonds_karp.cpp │ │ ├── gabow.cpp │ │ ├── gomory_hu.cpp │ │ ├── heavy_light.cpp │ │ ├── kuhn_munkres.cpp │ │ ├── link_cut.cpp │ │ └── scc.cpp │ ├── math │ │ ├── Makefile │ │ ├── crt.cpp │ │ ├── fft.cpp │ │ ├── floyd.cpp │ │ ├── frac.cpp │ │ ├── karatsuba.cpp │ │ ├── lis.cpp │ │ ├── miller_rabin.cpp │ │ ├── pollard.cpp │ │ ├── polynomials.cpp │ │ ├── romberg.cpp │ │ ├── sieve.cpp │ │ └── simplex.cpp │ ├── string │ │ ├── Makefile │ │ ├── aho_corasick.cpp │ │ ├── aho_corasick_2.cpp │ │ ├── karkkainen.cpp │ │ ├── manacher.cpp │ │ └── morris_pratt.cpp │ ├── structures │ │ ├── Makefile │ │ ├── bignum.cpp │ │ ├── heap.cpp │ │ └── treap.cpp │ ├── tests │ │ ├── babel.cpp │ │ ├── babel.in │ │ ├── babel.sol │ │ ├── babel_stl.cpp │ │ ├── babel_stl.in │ │ ├── babel_stl.sol │ │ ├── marques.cpp │ │ ├── marques.in │ │ ├── marques.sol │ │ ├── run_tests.py │ │ ├── run_tests.sh │ │ ├── test_coverage.sh │ │ └── test_list │ └── tex │ │ ├── Makefile │ │ ├── biblioteca.pdf │ │ ├── biblioteca.tex │ │ ├── docs.pt_BR.pdf │ │ ├── docs.pt_BR.tex │ │ ├── math_facts.tex │ │ └── mistakes.tex ├── biblioteca.pdf ├── bundle │ ├── all.pdf │ ├── centroids.pdf │ ├── codigos_sueltos.pdf │ ├── manual.pdf │ ├── notebook_fidel.pdf │ ├── notebook_mauricio.pdf │ ├── notebook_uniandes.pdf │ └── notebook_walter.pdf ├── centroids.pdf ├── codigos_sueltos │ ├── MonsterTrap_Gaizka.java │ ├── MonsterTrap_Gaizka.java.pdf │ ├── all.pdf │ ├── anas_flow.cpp │ ├── anas_flow.cpp.pdf │ ├── bridges.cpp │ ├── bridges.cpp.pdf │ ├── heavy_light_decomposition.cpp │ ├── heavy_light_decomposition.cpp.pdf │ ├── mcmf_walter.cpp │ ├── mcmf_walter.cpp.pdf │ ├── star_war_filipe_martins.cpp │ └── star_war_filipe_martins.cpp.pdf ├── notebook_fidel.pdf ├── notebook_gaizka.lyx ├── notebook_gaizka.pdf ├── notebook_uba.pdf ├── notebook_uniandes.pdf └── notebook_walter.pdf ├── pics ├── ancestors.1 ├── ancestors.mp ├── ascii-1.eps ├── ascii-1.svg ├── ascii-2.eps ├── ascii-2.svg ├── barycenter.png ├── circumcenter.png ├── cone.tikz ├── flights.1 ├── flights.mp ├── huzita.1 ├── huzita.mp ├── incenter.png ├── journey.1 ├── journey.mp ├── kingdom.1 ├── kingdom.mp ├── lanes.1 ├── lanes.mp ├── law_of_sines.png ├── makefile ├── manual-figure0.dpth ├── manual-figure0.md5 ├── manual-figure0.pdf ├── orthocenter.png ├── r.bat ├── rectangle.1 ├── rectangle.10 ├── rectangle.100 ├── rectangle.11 ├── rectangle.12 ├── rectangle.2 ├── rectangle.3 ├── rectangle.4 ├── rectangle.5 ├── rectangle.6 ├── rectangle.7 ├── rectangle.8 ├── rectangle.9 ├── rectangle.mp ├── reflected_point.1 ├── reflected_point.2 ├── reflected_point.mp ├── reflected_ray.1 └── reflected_ray.mp └── src ├── c++ ├── cout_con_precision.cpp ├── fgetws.cpp ├── io_file.cpp └── unicode.cpp ├── combinatoria ├── highlight.sh └── pascal_triangle.cpp ├── dp ├── lcs.cpp ├── lis.cpp └── particion_troncos.cpp ├── estructuras ├── fenwick.cpp ├── rmq │ ├── rmq_with_segment_tree.cpp │ └── rmq_with_table.cpp ├── rope.cpp ├── rope_test.cpp ├── segment_tree.cpp ├── treap.cpp └── treap_test.cpp ├── geometria ├── check_segment_intersection.cpp ├── circle_through_3_points.cpp ├── distance_point_to_line.cpp ├── distance_point_to_segment.cpp ├── grahamscan.cpp ├── great_circle_distance.cpp ├── highlight.sh ├── is_convex_polygon.cpp ├── is_inside_concave_polygon.cpp ├── is_inside_convex_polygon.cpp ├── line_line_intersection.cpp ├── minimum_enclosing_circle.cpp ├── monotonechain.cpp ├── parallelepiped_union_volume.cpp ├── polygon_area.cpp ├── rectangles_union_area.cpp ├── reflect_point.cpp ├── reflect_ray.cpp ├── segment_quadric_intersection.cpp ├── segment_segment_intersection.cpp ├── shortest_distances_in_3d.cpp └── split_convex_polygon.cpp ├── grafos ├── bellman.cpp ├── dijkstra.cpp ├── floyd.cpp ├── ford_fulkerson.cpp ├── ford_fulkerson_sparse.cpp ├── highlight.sh ├── konig.cpp ├── kruskal.cpp ├── lca.cpp ├── maximum_bipartite_matching.cpp ├── min_cost_max_flow.cpp ├── prim.cpp ├── puntos_articulacion.cpp └── tarjan.cpp ├── highlight.sh ├── java ├── highlight.sh ├── io_estandar.java ├── io_estandar_easy.java ├── io_file.java ├── maps_sets.java └── priority_queue.java ├── misc ├── highlight.sh ├── josephus.cpp ├── knight_distance.cpp ├── parser_recursivo_desc.cpp └── subsets_of_mask.cpp ├── strings ├── aho-corasick.cpp ├── dynamic_hashing.cpp ├── kmp.cpp ├── manacher.cpp ├── minimum_rotation.cpp ├── suffix_array.cpp └── z_algorithm.cpp ├── template.cpp └── teoria_de_numeros ├── bigmod.cpp ├── criba.cpp ├── divisores.cpp ├── highlight.sh └── inverso_modular.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.lol 2 | *.out 3 | *.toc 4 | *.aux 5 | *.auxlock 6 | *.log 7 | manual.synctex.gz 8 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all pdf ps pics clean 2 | 3 | all: pdf 4 | 5 | pdf: manual.pdf 6 | 7 | manualpics := $(patsubst %.mp,%.1,$(wildcard pics/[a-z]*.mp)) 8 | 9 | manual.pdf: manual.tex $(manualpics) 10 | pdflatex -shell-escape manual.tex 11 | pdflatex -shell-escape manual.tex 12 | 13 | pics/%.1: pics/%.mp 14 | make -C pics $(@F) 15 | 16 | clean: 17 | rm -f *.aux 18 | rm -f *.log 19 | rm -f *.dvi 20 | rm -f *.ps 21 | rm -f *.pdf 22 | make -C pics clean 23 | -------------------------------------------------------------------------------- /manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/manual.pdf -------------------------------------------------------------------------------- /other/README.md: -------------------------------------------------------------------------------- 1 | This directory contains stuff that is not in our notebook but 2 | it's still worth printing. 3 | 4 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/.gitignore: -------------------------------------------------------------------------------- 1 | .hg 2 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/.hgignore: -------------------------------------------------------------------------------- 1 | .*\.swp 2 | .*\.hash 3 | tests/.*\.bin 4 | tests/babel.out 5 | tests/babel$ 6 | tests/babel_stl.out 7 | tests/babel_stl$ 8 | tests/marques.out 9 | tests/marques$ 10 | tests/a.out 11 | tex/.*\.aux 12 | tex/.*\.log 13 | tex/.*\.toc 14 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/.todo: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Migrar o algoritmo de Dijkstra 5 | 6 | 7 | Implementar um Maxflow decente :) 8 | 9 | 10 | Implementar um mincost maxflow usando menores caminhos sucessivos com o relabeling de Edmonds e Karp 11 | 12 | 13 | Fix the range tree 14 | 15 | 16 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/Makefile: -------------------------------------------------------------------------------- 1 | all: tex 2 | 3 | view: all 4 | evince tex/biblioteca.pdf & 5 | 6 | LIBRARY_DIRS = config geometry graph math string structures 7 | ALL_DIRS = $(LIBRARY_DIRS) tex 8 | 9 | .PHONY: $(ALL_DIRS) view 10 | 11 | $(ALL_DIRS): 12 | $(MAKE) -C $@ 13 | 14 | tex: $(LIBRARY_DIRS) 15 | 16 | clean: 17 | for dir in $(ALL_DIRS); do \ 18 | $(MAKE) -C $$dir clean; \ 19 | done 20 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/config/Makefile: -------------------------------------------------------------------------------- 1 | FILES = .dotemacs.hash .hashgen.hash .template.cpp.hash .dotvimrc.hash .flymake.mk.hash 2 | 3 | all: $(FILES) 4 | 5 | .PHONY: clean 6 | 7 | $(FILES): .%.hash: % 8 | ../gen_hash.sh $< $@ 9 | 10 | clean: 11 | rm -f $(FILES) 12 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/config/dotemacs: -------------------------------------------------------------------------------- 1 | (global-font-lock-mode t) 2 | (setq transient-mark-mode t) 3 | 4 | (global-set-key [f5] 'cxx-compile) 5 | (defun cxx-compile() 6 | (interactive) 7 | (save-buffer) 8 | (compile (concat "g++ -g -O2 -o " (file-name-sans-extension buffer-file-name) 9 | " " buffer-file-name)) 10 | ) 11 | 12 | (add-hook 'c++-mode-hook (lambda () (c-set-style "stroustrup") 13 | (flymake-mode t))) 14 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/config/dotvimrc: -------------------------------------------------------------------------------- 1 | syn on 2 | set nocp number ai si ts=4 sts=4 sw=4 3 | ab #i #include 4 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/config/flymake.mk: -------------------------------------------------------------------------------- 1 | check-syntax: 2 | g++ -Wall -fsyntax-only $(CHK_SOURCES) 3 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/config/hashgen: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sed ':a;N;$!ba;s/[ \n\t]//g' | md5sum | cut -d' ' -f1 3 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/config/template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | int main() { 20 | } 21 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/gen_hash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | `dirname $0`/config/hashgen < $1 > $2 3 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/Makefile: -------------------------------------------------------------------------------- 1 | FILES = .point.cpp.hash .isect_primitives.cpp.hash .polygon_primitives.cpp.hash .misc_primitives.cpp.hash .hull.cpp.hash .kd_tree.cpp.hash .range_tree.cpp.hash .enclosing_circle.cpp.hash .closest_points.cpp.hash 2 | 3 | all: $(FILES) 4 | 5 | .PHONY: clean 6 | 7 | $(FILES): .%.hash: % 8 | ../gen_hash.sh $< $@ 9 | 10 | clean: 11 | rm -f $(FILES) 12 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/closest_points.cpp: -------------------------------------------------------------------------------- 1 | pair closest_points_rec(vector& px, vector& py) { 2 | pair ret; 3 | double d; 4 | 5 | if(px.size() <= 3) { 6 | double best = 1e10; 7 | for(int i = 0; i < px.size(); ++i) 8 | for(int j = i + 1; j < px.size(); ++j) 9 | if(dist(px[i], px[j]) < best) { 10 | ret = make_pair(px[i], px[j]); 11 | best = dist(px[i], px[j]); 12 | } 13 | 14 | return ret; 15 | } 16 | 17 | pt split = px[(px.size() - 1)/2]; 18 | vector qx, qy, rx, ry; 19 | for(int i = 0; i < px.size(); ++i) 20 | if(px[i] <= split) qx.push_back(px[i]); 21 | else rx.push_back(px[i]); 22 | 23 | for(int i = 0; i < py.size(); ++i) 24 | if(py[i] <= split) qy.push_back(py[i]); 25 | else ry.push_back(py[i]); 26 | 27 | ret = closest_points_rec(qx, qy); 28 | pair rans = closest_points_rec(rx, ry); 29 | double delta = dist(ret.first, ret.second); 30 | 31 | if((d = dist(rans.first, rans.second)) < delta) { 32 | delta = d; 33 | ret = rans; 34 | } 35 | 36 | vector s; 37 | for(int i = 0; i < py.size(); ++i) 38 | if(cmp(abs(py[i].x - split.x), delta) <= 0) 39 | s.push_back(py[i]); 40 | 41 | for(int i = 0; i < s.size(); ++i) 42 | for(int j = 1; j <= 7 && i + j < s.size(); ++j) 43 | if((d = dist(s[i], s[i+j])) < delta) { 44 | delta = d; 45 | ret = make_pair(s[i], s[i+j]); 46 | } 47 | 48 | return ret; 49 | } 50 | 51 | pair closest_points(vector pts) { 52 | if(pts.size() == 1) return make_pair(pt(-INF, -INF), pt(INF, INF)); 53 | 54 | sort(pts.begin(), pts.end()); 55 | for(int i = 0; i + 1 < pts.size(); ++i) 56 | if(pts[i] == pts[i+1]) 57 | return make_pair(pts[i], pts[i+1]); 58 | 59 | vector py = pts; 60 | sort(py.begin(), py.end(), compy); 61 | return closest_points_rec(pts, py); 62 | } 63 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/enclosing_circle.cpp: -------------------------------------------------------------------------------- 1 | circle enclosing_circle(vector& pts) { 2 | srand(unsigned(time(0))); 3 | random_shuffle(pts.begin(), pts.end()); 4 | 5 | circle c(pt(), -1); 6 | for(int i = 0; i < pts.size(); ++i) { 7 | if(point_circle(pts[i], c)) continue; 8 | c = circle(pts[i], 0); 9 | for(int j = 0; j < i; ++j) { 10 | if(point_circle(pts[j], c)) continue; 11 | c = circle((pts[i] + pts[j])/2, abs(pts[i] - pts[j])/2); 12 | for(int k = 0; k < j; ++k) { 13 | if(point_circle(pts[k], c)) continue; 14 | pt center = circumcenter(pts[i], pts[j], pts[k]); 15 | c = circle(center, abs(center - pts[i])/2); 16 | } 17 | } 18 | } 19 | return c; 20 | } 21 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/hull.cpp: -------------------------------------------------------------------------------- 1 | pt pivot; 2 | 3 | bool hull_comp(pt a, pt b) { 4 | int turn = ccw(a, b, pivot); 5 | return turn == 1 || (turn == 0 && cmp(norm(a-pivot), norm(b-pivot)) < 0); 6 | } 7 | 8 | vector hull(vector pts) { 9 | if(pts.size() <= 1) return pts; 10 | vector ret; 11 | 12 | int mini = 0; 13 | for(int i = 1; i < pts.size(); ++i) 14 | if(pts[i] < pts[mini]) 15 | mini = i; 16 | 17 | pivot = pts[mini]; 18 | swap(pts[0], pts[mini]); 19 | sort(pts.begin() + 1, pts.end(), hull_comp); 20 | 21 | ret.push_back(pts[0]); 22 | ret.push_back(pts[1]); 23 | int sz = 2; 24 | 25 | for(int i = 2; i < pts.size(); ++i) { 26 | while(sz >= 2 && ccw(ret[sz-2], ret[sz-1], pts[i]) <= 0) 27 | ret.pop_back(), --sz; 28 | ret.push_back(pts[i]), ++sz; 29 | } 30 | 31 | return ret; 32 | } 33 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/isect_primitives.cpp: -------------------------------------------------------------------------------- 1 | bool in_rect(pt a, pt b, pt c) { 2 | return sgn(c.x - min(a.x, b.x)) >= 0 && sgn(max(a.x, b.x) - c.x) >= 0 && 3 | sgn(c.y - min(a.y, b.y)) >= 0 && sgn(max(a.y, b.y) - c.y) >= 0; 4 | } 5 | bool ps_isects(pt a, pt b, pt c) { return ccw(a,b,c) == 0 && in_rect(a,b,c); } 6 | 7 | bool ss_isects(pt a, pt b, pt c, pt d) { 8 | if (ccw(a,b,c)*ccw(a,b,d) == -1 && ccw(c,d,a)*ccw(c,d,b) == -1) return true; 9 | return ps_isects(a, b, c) || ps_isects(a, b, d) || 10 | ps_isects(c, d, a) || ps_isects(c, d, b); 11 | } 12 | 13 | pt parametric_isect(pt p, pt v, pt q, pt w) { 14 | double t = ((q-p)%w)/(v%w); 15 | return p + v*t; 16 | } 17 | 18 | pt ss_isect(pt p, pt q, pt r, pt s) { 19 | pt isect = parametric_isect(p, q-p, r, s-r); 20 | if(ps_isects(p, q, isect) && ps_isects(r, s, isect)) return isect; 21 | return pt(1/0.0, 1/0.0); 22 | } 23 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/kd_tree.cpp: -------------------------------------------------------------------------------- 1 | int tree[4*MAXSZ], val[4*MAXSZ]; 2 | TYPE split[4*MAXSZ]; 3 | vector pts; 4 | 5 | void kd_recurse(int root, int left, int right, bool x) { 6 | if(left == right) { 7 | tree[root] = left; 8 | val[root] = 1; 9 | return; 10 | } 11 | 12 | int mid = (right+left)/2; 13 | nth_element(pts.begin() + left, pts.begin() + mid, 14 | pts.begin() + right + 1, x ? compx : compy); 15 | split[root] = x ? pts[mid].x : pts[mid].y; 16 | 17 | kd_recurse(2*root+1, left, mid, !x); 18 | kd_recurse(2*root+2, mid+1, right, !x); 19 | 20 | val[root] = val[2*root+1] + val[2*root+2]; 21 | } 22 | 23 | void kd_build() { 24 | memset(tree, -1, sizeof tree); 25 | kd_recurse(0, 0, pts.size() - 1, true); 26 | } 27 | 28 | int kd_query(int root, TYPE a, TYPE b, TYPE c, TYPE d, TYPE ca = -INF, 29 | TYPE cb = INF, TYPE cc = -INF, TYPE cd = INF, bool x = true) { 30 | if(a <= ca && cb <= b && c <= cc && cd <= d) 31 | return val[root]; 32 | 33 | if(tree[root] != -1) 34 | return a <= pts[tree[root]].x && pts[tree[root]].x <= b && 35 | c <= pts[tree[root]].y && pts[tree[root]].y <= d ? val[root] : 0; 36 | 37 | int ret = 0; 38 | if(x) { 39 | if(a <= split[root]) 40 | ret += kd_query(2*root+1, a, b, c, d, ca, split[root], cc, cd, !x); 41 | if(split[root] <= b) 42 | ret += kd_query(2*root+2, a, b, c, d, split[root], cb, cc, cd, !x); 43 | } else { 44 | if(c <= split[root]) 45 | ret += kd_query(2*root+1, a, b, c, d, ca, cb, cc, split[root], !x); 46 | if(split[root] <= d) 47 | ret += kd_query(2*root+2, a, b, c, d, ca, cb, split[root], cd, !x); 48 | } 49 | return ret; 50 | } 51 | 52 | pt kd_neighbor(int root, pt a, bool x) { 53 | if(tree[root] != -1) 54 | return a == pts[tree[root]] ? pt(INF, INF) : pts[tree[root]]; 55 | 56 | TYPE num = x ? a.x : a.y; 57 | int term = num <= split[root] ? 1 : 2; 58 | pt ret; 59 | 60 | TYPE d = norm(a - (ret = kd_neighbor(2*root + term, a, !x))); 61 | if((split[root] - num)*(split[root] - num) < d) { 62 | pt ret2 = kd_neighbor(2*root + 3 - term, a, !x); 63 | if(norm(a - ret2) < d) 64 | ret = ret2; 65 | } 66 | 67 | return ret; 68 | } 69 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/misc_primitives.cpp: -------------------------------------------------------------------------------- 1 | bool point_circle(pt p, circle c) { 2 | return cmp(abs(p - c.c), c.r) <= 0; 3 | } 4 | 5 | double ps_distance(pt p, pt a, pt b) { 6 | p = p - a; b = b - a; 7 | double coef = min(max((b||p)/(b||b), TYPE(0)), TYPE(1)); 8 | return abs(p - b*coef); 9 | } 10 | 11 | pt circumcenter(pt a, pt b, pt c) { 12 | return parametric_isect((b+a)/2, (b-a)*I, (c+a)/2, (c-a)*I); 13 | } 14 | 15 | bool compy(pt a, pt b) { 16 | return cmp(a.y, b.y) ? cmp(a.y, b.y) < 0 : cmp(a.x, b.x) < 0; 17 | } 18 | bool compx(pt a, pt b) { return a < b; } 19 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/point.cpp: -------------------------------------------------------------------------------- 1 | typedef double TYPE; 2 | const TYPE EPS = 1e-9, INF = 1e9; 3 | 4 | inline int sgn(TYPE a) { return a > EPS ? 1 : (a < -EPS ? -1 : 0); } 5 | inline int cmp(TYPE a, TYPE b) { return sgn(a - b); } 6 | 7 | struct pt { 8 | TYPE x, y; 9 | pt(TYPE x = 0, TYPE y = 0) : x(x), y(y) { } 10 | 11 | bool operator==(pt p) { return cmp(x, p.x) == 0 && cmp(y, p.y) == 0; } 12 | bool operator<(pt p) const { 13 | return cmp(x, p.x) ? cmp(x, p.x) < 0 : cmp(y, p.y) < 0; 14 | } 15 | bool operator<=(pt p) { return *this < p || *this == p; } 16 | TYPE operator||(pt p) { return x*p.x + y*p.y; } 17 | TYPE operator%(pt p) { return x*p.y - y*p.x; } 18 | pt operator~() { return pt(x, -y); } 19 | pt operator+(pt p) { return pt(x + p.x, y + p.y); } 20 | pt operator-(pt p) { return pt(x - p.x, y - p.y); } 21 | pt operator*(pt p) { return pt(x*p.x - y*p.y, x*p.y + y*p.x); } 22 | pt operator/(TYPE t) { return pt(x/t, y/t); } 23 | pt operator/(pt p) { return (*this * ~p)/(p||p); } 24 | }; 25 | const pt I = pt(0,1); 26 | 27 | struct circle { 28 | pt c; TYPE r; 29 | circle(pt c, TYPE r) : c(c), r(r) { } 30 | }; 31 | 32 | TYPE norm(pt a) { return a||a; } 33 | TYPE abs(pt a) { return sqrt(a||a); } 34 | TYPE dist(pt a, pt b) { return abs(a - b); } 35 | TYPE area(pt a, pt b, pt c) { return (a-c)%(b-c); } 36 | int ccw(pt a, pt b, pt c) { return sgn(area(a, b, c)); } 37 | pt unit(pt a) { return a/abs(a); } 38 | double arg(pt a) { return atan2(a.y, a.x); } 39 | pt f_polar(TYPE mod, double ang) { return pt(mod * cos(ang), mod * sin(ang)); } 40 | inline int g_mod(int i, int n) { if(i == n) return 0; return i; } 41 | 42 | ostream& operator<<(ostream& o, pt p) { 43 | return o << "(" << p.x << "," << p.y << ")"; 44 | } 45 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/polygon_primitives.cpp: -------------------------------------------------------------------------------- 1 | double p_signedarea(vector& pol) { 2 | double ret = 0; 3 | for(int i = 0; i < pol.size(); ++i) 4 | ret += pol[i] % pol[g_mod(i+1, pol.size())]; 5 | return ret/2; 6 | } 7 | 8 | int point_polygon(pt p, vector& pol) { 9 | int n = pol.size(), count = 0; 10 | 11 | for(int i = 0; i < n; ++i) { 12 | int i1 = g_mod(i+1, n); 13 | if (ps_isects(pol[i], pol[i1], p)) return -1; 14 | else if(((sgn(pol[i].y - p.y) == 1) != (sgn(pol[i1].y - p.y) == 1)) && 15 | ccw(pol[i], p, pol[i1]) == sgn(pol[i].y - pol[i1].y)) ++count; 16 | } 17 | return count % 2; 18 | } 19 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/geometry/range_tree.cpp: -------------------------------------------------------------------------------- 1 | vector pts, tree[MAXSZ]; 2 | vector xs; 3 | vector lnk[MAXSZ][2]; 4 | 5 | int rt_recurse(int root, int left, int right) { 6 | lnk[root][0].clear(); lnk[root][1].clear(); tree[root].clear(); 7 | 8 | if(left == right) { 9 | vector::iterator it; 10 | it = lower_bound(pts.begin(), pts.end(), pt(xs[left], -INF)); 11 | for(; it != pts.end() && cmp(it->x, xs[left]) == 0; ++it) 12 | tree[root].push_back(*it); 13 | return tree[root].size(); 14 | } 15 | 16 | int mid = (left + right)/2, cl = 2*root + 1, cr = cl + 1; 17 | int sz1 = rt_recurse(cl, left, mid); 18 | int sz2 = rt_recurse(cr, mid + 1, right); 19 | 20 | lnk[root][0].reserve(sz1+sz2+1); 21 | lnk[root][1].reserve(sz1+sz2+1); 22 | tree[root].reserve(sz1+sz2); 23 | 24 | int l = 0, r = 0, llink = 0, rlink = 0; pt last; 25 | while(l < sz1 || r < sz2) { 26 | if(r == sz2 || (l < sz1 && compy(tree[cl][l], tree[cr][r]))) 27 | tree[root].push_back(last = tree[cl][l++]); 28 | else tree[root].push_back(last = tree[cr][r++]); 29 | 30 | while(llink < sz1 && compy(tree[cl][llink], last)) 31 | ++llink; 32 | while(rlink < sz2 && compy(tree[cr][rlink], last)) 33 | ++rlink; 34 | 35 | lnk[root][0].push_back(llink); 36 | lnk[root][1].push_back(rlink); 37 | } 38 | 39 | lnk[root][0].push_back(tree[cl].size()); 40 | lnk[root][1].push_back(tree[cr].size()); 41 | 42 | return tree[root].size(); 43 | } 44 | 45 | void rt_build() { 46 | sort(pts.begin(), pts.end()); 47 | xs.clear(); 48 | for(int i = 0; i < pts.size(); ++i) xs.push_back(pts[i].x); 49 | xs.erase(unique(xs.begin(), xs.end()), xs.end()); 50 | rt_recurse(0, 0, xs.size() - 1); 51 | } 52 | 53 | int rt_query(int root, int l, int r, TYPE a, TYPE b, TYPE c, TYPE d, 54 | int posl = -1, int posr = -1) { 55 | if(root == 0 && posl == -1) { 56 | posl = lower_bound(tree[0].begin(), tree[0].end(), pt(a, c), compy) 57 | - tree[0].begin(); 58 | posr = upper_bound(tree[0].begin(), tree[0].end(), pt(b, d), compy) 59 | - tree[0].begin(); 60 | } 61 | 62 | if(posl == posr) return 0; 63 | if(a <= xs[l] && xs[r] <= b) 64 | return posr - posl; 65 | 66 | int mid = (l+r)/2, ret = 0; 67 | if(cmp(a, xs[mid]) <= 0) 68 | ret += rt_query(2*root+1, l, mid, a, b, c, d, 69 | lnk[root][0][posl], lnk[root][0][posr]); 70 | if(cmp(xs[mid+1], b) <= 0) 71 | ret += rt_query(2*root+2, mid+1, r, a, b, c, d, 72 | lnk[root][1][posl], lnk[root][1][posr]); 73 | return ret; 74 | } 75 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/Makefile: -------------------------------------------------------------------------------- 1 | FILES = .busacker_gowen.cpp.hash .dinic.cpp.hash .gabow.cpp.hash .scc.cpp.hash .link_cut.cpp.hash .gomory_hu.cpp.hash .heavy_light.cpp.hash .kuhn_munkres.cpp.hash 2 | 3 | all: $(FILES) 4 | 5 | .PHONY: clean 6 | 7 | $(FILES): .%.hash: % 8 | ../gen_hash.sh $< $@ 9 | 10 | clean: 11 | rm -f $(FILES) 12 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/busacker_gowen.cpp: -------------------------------------------------------------------------------- 1 | int dist[MAXV], last_edge[MAXV], d_visited[MAXV], bg_prev[MAXV], pot[MAXV], 2 | capres[MAXV]; 3 | int prev_edge[MAXE], adj[MAXE], cap[MAXE], cost[MAXE], flow[MAXE]; 4 | 5 | int nedges; 6 | priority_queue > d_q; 7 | 8 | inline void bg_edge(int v, int w, int capacity, int cst, bool r = false) { 9 | prev_edge[nedges] = last_edge[v]; 10 | adj[nedges] = w; 11 | cap[nedges] = capacity; 12 | flow[nedges] = 0; 13 | cost[nedges] = cst; 14 | last_edge[v] = nedges++; 15 | 16 | if(!r) bg_edge(w, v, 0, -cst, true); 17 | } 18 | 19 | inline int rev(int i) { return i ^ 1; } 20 | inline int from(int i) { return adj[rev(i)]; } 21 | 22 | inline void bg_init() { 23 | nedges = 0; 24 | memset(last_edge, -1, sizeof last_edge); 25 | memset(pot, 0, sizeof pot); 26 | } 27 | 28 | void bg_dijkstra(int s, int num_nodes = MAXV) { 29 | memset(dist, 0x3f, sizeof dist); 30 | memset(d_visited, 0, sizeof d_visited); 31 | d_q.push(make_pair(dist[s] = 0, s)); 32 | capres[s] = 0x3f3f3f3f; 33 | 34 | while(!d_q.empty()) { 35 | int v = d_q.top().second; d_q.pop(); 36 | if(d_visited[v]) continue; d_visited[v] = true; 37 | 38 | for(int i = last_edge[v]; i != -1; i = prev_edge[i]) { 39 | if(cap[i] - flow[i] == 0) continue; 40 | int w = adj[i], new_dist = dist[v] + cost[i] + pot[v] - pot[w]; 41 | 42 | if(new_dist < dist[w]) { 43 | d_q.push(make_pair(-(dist[w] = new_dist), w)); 44 | bg_prev[w] = rev(i); 45 | capres[w] = min(capres[v], cap[i] - flow[i]); 46 | } 47 | } 48 | } 49 | } 50 | 51 | pair busacker_gowen(int src, int sink, int num_nodes = MAXV) { 52 | int ret_flow = 0, ret_cost = 0; 53 | 54 | bg_dijkstra(src, num_nodes); 55 | while(dist[sink] < 0x3f3f3f3f) { 56 | int cur = sink; 57 | while(cur != src) { 58 | flow[bg_prev[cur]] -= capres[sink]; 59 | flow[rev(bg_prev[cur])] += capres[sink]; 60 | ret_cost += cost[rev(bg_prev[cur])] * capres[sink]; 61 | cur = adj[bg_prev[cur]]; 62 | } 63 | ret_flow += capres[sink]; 64 | 65 | for(int i = 0; i < MAXV; ++i) 66 | pot[i] = min(pot[i] + dist[i], 0x3f3f3f3f); 67 | 68 | bg_dijkstra(src, num_nodes); 69 | } 70 | return make_pair(ret_flow, ret_cost); 71 | } 72 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/dijkstra_sparse_fast.cpp: -------------------------------------------------------------------------------- 1 | int dist[MAXV], last_edge[MAXV]; 2 | int prev_edge[MAXE], weight[MAXE], adj[MAXE]; 3 | int nedges; 4 | heap d_h; 5 | 6 | void d_init() { 7 | nedges = 0; 8 | memset(last_edge, -1, sizeof last_edge); 9 | } 10 | 11 | void d_edge(int v, int w, int eweight) { 12 | prev_edge[nedges] = last_edge[v]; 13 | weight[nedges] = eweight; 14 | adj[nedges] = w; 15 | last_edge[v] = nedges++; 16 | } 17 | 18 | void dijkstra(int s, int num_nodes = MAXV) { 19 | memset(dist, 0x3f, sizeof dist); 20 | d_h.init(num_nodes); 21 | d_h.decrease_key(s, dist[s] = 0); 22 | 23 | while(d_h.size > 0) { 24 | int v = d_h.extract_min(); 25 | 26 | for(int i = last_edge[v]; i != -1; i = prev_edge[i]) { 27 | int w = adj[i], new_dist = dist[v] + weight[i]; 28 | if(new_dist < dist[w]) 29 | d_h.decrease_key(w, dist[w] = new_dist); 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/dijkstra_sparse_small.cpp: -------------------------------------------------------------------------------- 1 | int dist[MAXV], last_edge[MAXV], d_visited[MAXV]; 2 | int prev_edge[MAXE], weight[MAXE], adj[MAXE]; 3 | int nedges; 4 | priority_queue > d_q; 5 | 6 | void d_init() { 7 | nedges = 0; 8 | memset(last_edge, -1, sizeof last_edge); 9 | } 10 | 11 | void d_edge(int v, int w, int eweight) { 12 | prev_edge[nedges] = last_edge[v]; 13 | weight[nedges] = eweight; 14 | adj[nedges] = w; 15 | last_edge[v] = nedges++; 16 | } 17 | 18 | void dijkstra(int s, int num_nodes = MAXV) { 19 | memset(dist, 0x3f, sizeof dist); 20 | memset(d_visited, 0, sizeof d_visited); 21 | d_q.push(make_pair(dist[s] = 0, s)); 22 | 23 | while(!d_q.empty()) { 24 | int v = d_q.top().second; d_q.pop(); 25 | if(d_visited[v]) continue; d_visited[v] = true; 26 | 27 | for(int i = last_edge[v]; i != -1; i = prev_edge[i]) { 28 | int w = adj[i], new_dist = dist[v] + weight[i]; 29 | if(new_dist < dist[w]) 30 | d_q.push(make_pair(-(dist[w] = new_dist), w)); 31 | } 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/dinic.cpp: -------------------------------------------------------------------------------- 1 | int last_edge[MAXV], cur_edge[MAXV], dist[MAXV]; 2 | int prev_edge[MAXE], cap[MAXE], flow[MAXE], adj[MAXE]; 3 | int nedges; 4 | 5 | void d_init() { 6 | nedges = 0; 7 | memset(last_edge, -1, sizeof last_edge); 8 | } 9 | 10 | void d_edge(int v, int w, int capacity, bool r = false) { 11 | prev_edge[nedges] = last_edge[v]; 12 | cap[nedges] = capacity; 13 | adj[nedges] = w; 14 | flow[nedges] = 0; 15 | last_edge[v] = nedges++; 16 | 17 | if(!r) d_edge(w, v, 0, true); 18 | } 19 | 20 | bool d_auxflow(int source, int sink) { 21 | queue q; 22 | q.push(source); 23 | 24 | memset(dist, -1, sizeof dist); 25 | dist[source] = 0; 26 | memcpy(cur_edge, last_edge, sizeof last_edge); 27 | 28 | while(!q.empty()) { 29 | int v = q.front(); q.pop(); 30 | for(int i = last_edge[v]; i != -1; i = prev_edge[i]) { 31 | if(cap[i] - flow[i] == 0) continue; 32 | 33 | if(dist[adj[i]] == -1) { 34 | dist[adj[i]] = dist[v] + 1; 35 | q.push(adj[i]); 36 | 37 | if(adj[i] == sink) return true; 38 | } 39 | } 40 | } 41 | 42 | return false; 43 | } 44 | 45 | int d_augmenting(int v, int sink, int c) { 46 | if(v == sink) return c; 47 | 48 | for(int& i = cur_edge[v]; i != -1; i = prev_edge[i]) { 49 | if(cap[i] - flow[i] == 0 || dist[adj[i]] != dist[v] + 1) 50 | continue; 51 | 52 | int val; 53 | if(val = d_augmenting(adj[i], sink, min(c, cap[i] - flow[i]))) { 54 | flow[i] += val; 55 | flow[i^1] -= val; 56 | return val; 57 | } 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | int dinic(int source, int sink) { 64 | int ret = 0; 65 | while(d_auxflow(source, sink)) { 66 | int flow; 67 | while(flow = d_augmenting(source, sink, 0x3f3f3f3f)) 68 | ret += flow; 69 | } 70 | 71 | return ret; 72 | } 73 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/edmonds_karp.cpp: -------------------------------------------------------------------------------- 1 | int last_edge[MAXV], ek_visited[MAXV], ek_prev[MAXV], ek_capres[MAXV]; 2 | int prev_edge[MAXE], cap[MAXE], flow[MAXE], adj[MAXE]; 3 | int nedges; 4 | 5 | void ek_init() { 6 | nedges = 0; 7 | memset(last_edge, -1, sizeof last_edge); 8 | } 9 | 10 | void ek_edge(int v, int w, int capacity, bool r = false) { 11 | prev_edge[nedges] = last_edge[v]; 12 | cap[nedges] = capacity; 13 | adj[nedges] = w; 14 | flow[nedges] = 0; 15 | last_edge[v] = nedges++; 16 | 17 | if(!r) ek_edge(w, v, 0, true); 18 | } 19 | 20 | queue ek_q; 21 | 22 | inline int rev(int i) { return i ^ 1; } 23 | 24 | int ek_bfs(int src, int sink, int num_nodes) { 25 | memset(ek_visited, 0, sizeof(int) * num_nodes); 26 | 27 | ek_q = queue(); 28 | ek_q.push(src); 29 | ek_capres[src] = 0x3f3f3f3f; 30 | 31 | while(!ek_q.empty()) { 32 | int v = ek_q.front(); ek_q.pop(); 33 | if(v == sink) return ek_capres[sink]; 34 | ek_visited[v] = 2; 35 | 36 | for(int i = last_edge[v]; i != -1; i = prev_edge[i]) { 37 | int w = adj[i], new_capres = min(cap[i] - flow[i], ek_capres[v]); 38 | if(new_capres <= 0) continue; 39 | 40 | if(!ek_visited[w]) { 41 | ek_prev[w] = rev(i); 42 | ek_capres[w] = new_capres; 43 | 44 | ek_visited[w] = 1; 45 | ek_q.push(w); 46 | } 47 | } 48 | } 49 | return 0; 50 | } 51 | 52 | int edmonds_karp(int src, int sink, int num_nodes = MAXV) { 53 | int ret = 0, new_flow; 54 | 55 | while((new_flow = ek_bfs(src, sink, num_nodes)) > 0) { 56 | int cur = sink; 57 | while(cur != src) { 58 | flow[ek_prev[cur]] -= new_flow; 59 | flow[rev(ek_prev[cur])] += new_flow; 60 | cur = adj[ek_prev[cur]]; 61 | } 62 | ret += new_flow; 63 | } 64 | return ret; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/gabow.cpp: -------------------------------------------------------------------------------- 1 | int prev_edge[MAXE], v[MAXE], w[MAXE], last_edge[MAXV]; 2 | int type[MAXV], label[MAXV], first[MAXV], mate[MAXV], nedges; 3 | bool g_flag[MAXV], g_souter[MAXV]; 4 | 5 | void g_init() { 6 | nedges = 0; 7 | memset(last_edge, -1, sizeof last_edge); 8 | } 9 | 10 | void g_edge(int a, int b, bool rev = false) { 11 | prev_edge[nedges] = last_edge[a]; 12 | v[nedges] = a; 13 | w[nedges] = b; 14 | last_edge[a] = nedges++; 15 | 16 | if(!rev) return g_edge(b, a, true); 17 | } 18 | 19 | void g_label(int v, int join, int edge, queue& outer) { 20 | if(v == join) return; 21 | if(label[v] == -1) outer.push(v); 22 | 23 | label[v] = edge; 24 | type[v] = 1; 25 | first[v] = join; 26 | 27 | g_label(first[label[mate[v]]], join, edge, outer); 28 | } 29 | 30 | void g_augment(int _v, int _w) { 31 | int t = mate[_v]; 32 | mate[_v] = _w; 33 | 34 | if(mate[t] != _v) return; 35 | if(label[_v] == -1) return; 36 | 37 | if(type[_v] == 0) { 38 | mate[t] = label[_v]; 39 | g_augment(label[_v], t); 40 | } else if(type[_v] == 1) { 41 | g_augment(v[label[_v]], w[label[_v]]); 42 | g_augment(w[label[_v]], v[label[_v]]); 43 | } 44 | } 45 | 46 | int gabow(int n) { 47 | memset(mate, -1, sizeof mate); 48 | memset(first, -1, sizeof first); 49 | 50 | int ret = 0; 51 | for(int z = 0; z < n; ++z) { 52 | if(mate[z] != -1) continue; 53 | 54 | memset(label, -1, sizeof label); 55 | memset(type, -1, sizeof type); 56 | memset(g_souter, 0, sizeof g_souter); 57 | 58 | label[z] = -1; type[z] = 0; 59 | 60 | queue outer; 61 | outer.push(z); 62 | 63 | bool done = false; 64 | while(!outer.empty()) { 65 | int x = outer.front(); outer.pop(); 66 | 67 | if(g_souter[x]) continue; 68 | g_souter[x] = true; 69 | 70 | for(int i = last_edge[x]; i != -1; i = prev_edge[i]) { 71 | if(mate[w[i]] == -1 && w[i] != z) { 72 | mate[w[i]] = x; 73 | g_augment(x, w[i]); 74 | ++ret; 75 | 76 | done = true; 77 | break; 78 | } 79 | 80 | if(type[w[i]] == -1) { 81 | int v = mate[w[i]]; 82 | if(type[v] == -1) { 83 | type[v] = 0; 84 | label[v] = x; 85 | outer.push(v); 86 | 87 | first[v] = w[i]; 88 | } 89 | continue; 90 | } 91 | 92 | int r = first[x], s = first[w[i]]; 93 | if(r == s) continue; 94 | 95 | memset(g_flag, 0, sizeof g_flag); 96 | g_flag[r] = g_flag[s] = true; 97 | 98 | while(r != -1 || s != -1) { 99 | if(s != -1) swap(r, s); 100 | r = first[label[mate[r]]]; 101 | if(r == -1) continue; 102 | if(g_flag[r]) break; g_flag[r] = true; 103 | } 104 | 105 | g_label(first[x], r, i, outer); 106 | g_label(first[w[i]], r, i, outer); 107 | 108 | for(int c = 0; c < n; ++c) 109 | if(type[c] != -1 && first[c] != -1 && type[first[c]] != -1) 110 | first[c] = r; 111 | } 112 | if(done) break; 113 | } 114 | } 115 | return ret; 116 | } 117 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/gomory_hu.cpp: -------------------------------------------------------------------------------- 1 | bool cut[MAXV]; 2 | int mincut(int s, int t) { 3 | memset(flow, 0, sizeof flow); 4 | memset(cut, 0, sizeof cut); 5 | int ret = dinic(s, t); 6 | 7 | queue q; 8 | q.push(s); cut[s] = true; 9 | while(!q.empty()) { 10 | int v = q.front(); q.pop(); 11 | for(int i = last_edge[v]; i != -1; i = prev_edge[i]) { 12 | int w = adj[i]; 13 | if(cap[i] - flow[i] && !cut[w]) 14 | cut[w] = true, q.push(w); 15 | } 16 | } 17 | 18 | return ret; 19 | } 20 | 21 | int up[MAXV], val[MAXV]; 22 | void gomory_hu(int n) { 23 | memset(up, 0, sizeof up); 24 | for(int i = 1; i < n; i++) { 25 | val[i] = mincut(i, up[i]); 26 | for(int j = i+1; j < n; j++) 27 | if(cut[j] && up[j] == up[i]) 28 | up[j] = i; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/heavy_light.cpp: -------------------------------------------------------------------------------- 1 | int last_edge[MAXV], prev_edge[MAXE], adj[MAXE], nedges; 2 | int up[MAXV], subtree[MAXV], path[MAXV], offset[MAXV], depth[MAXV]; 3 | int nump, numv, psize[MAXV], pfirst[MAXV], walk[MAXV]; 4 | 5 | struct stree { 6 | vector data; 7 | int sz; 8 | 9 | explicit stree(int tsz) : sz(1) { 10 | while(sz < tsz) sz *= 2; 11 | data.resize(2*sz); 12 | } 13 | 14 | int query(int a, int b, int root, int l, int r) { 15 | if(l == a && r == b) return data[root]; 16 | int mid = (l+r)/2, ans = 0; 17 | if(a <= mid) ans = max(ans, query(a, min(b, mid), 2*root+1, l, mid)); 18 | if(b > mid) ans = max(ans, query(max(a, mid+1), b, 2*root+2, mid+1, r)); 19 | return ans; 20 | } 21 | int query(int a, int b) { return a<=b ? query(a, b, 0, 0, sz-1) : 0; } 22 | 23 | void update(int pos, int val, int root, int l, int r) { 24 | if(l == r) { data[root] = val; return; } 25 | int mid = (l+r)/2; 26 | if(pos <= mid) update(pos, val, 2*root+1, l, mid); 27 | else update(pos, val, 2*root+2, mid+1, r); 28 | data[root] = max(data[2*root+1], data[2*root+2]); 29 | } 30 | void update(int pos, int val) { update(pos, val, 0, 0, sz-1); } 31 | }; 32 | 33 | void hl_init(int n) { 34 | memset(last_edge, -1, sizeof(int) * n); 35 | nedges = 0; 36 | } 37 | 38 | void hl_edge(int a, int b, bool rev = false) { 39 | prev_edge[nedges] = last_edge[a]; 40 | adj[nedges] = b; 41 | last_edge[a] = nedges++; 42 | 43 | if(!rev) hl_edge(b, a, true); 44 | } 45 | 46 | vector segtree; 47 | void heavy_light() { 48 | memset(up, -1, sizeof up); 49 | stack s; if(last_edge[0] != -1) s.push(last_edge[0]); 50 | 51 | walk[0] = depth[0] = up[0] = 0; numv = subtree[0] = 1; 52 | while(!s.empty()) { 53 | int i = s.top(), v = adj[i^1], w = adj[i]; 54 | if(up[w] == -1) { 55 | up[w] = v; depth[w] = depth[v]+1; subtree[w] = 1; 56 | walk[numv++] = w; s.push(last_edge[w]); 57 | } else { 58 | s.pop(); if(up[w] == v) subtree[v] += subtree[w]; 59 | if(prev_edge[i] != -1) s.push(prev_edge[i]); 60 | } 61 | } 62 | 63 | pfirst[0] = path[0] = offset[0] = 0; nump = psize[0] = 1; 64 | for(int i = 1; i < numv; i++) { 65 | int v = walk[i], p = up[v]; 66 | if(2*subtree[v] < subtree[p] || p == 0) 67 | offset[v] = 0, path[v] = nump, pfirst[nump] = v, psize[nump++] = 1; 68 | else 69 | offset[v] = offset[p]+1, path[v] = path[p], psize[path[v]]++; 70 | } 71 | 72 | segtree.clear(); segtree.reserve(nump); 73 | for(int i = 0; i < nump; i++) segtree.push_back(stree(psize[i])); 74 | } 75 | 76 | int lca(int v, int w) { 77 | int fpv = pfirst[path[v]], fpw = pfirst[path[w]]; 78 | while(v != 0 && w != 0 && fpv != fpw) { 79 | if(depth[up[fpv]] > depth[up[fpw]]) swap(v, w), swap(fpv, fpw); 80 | w = up[fpw]; fpw = pfirst[path[w]]; 81 | } 82 | return depth[v] < depth[w] ? v : w; 83 | } 84 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/kuhn_munkres.cpp: -------------------------------------------------------------------------------- 1 | int w[MAXV][MAXV], s[MAXV], rem[MAXV], remx[MAXV]; 2 | int mx[MAXV], my[MAXV], lx[MAXV], ly[MAXV]; 3 | 4 | void add(int x, int n) { 5 | s[x] = true; 6 | for(int y = 0; y < n; y++) 7 | if(rem[y] != -INF && rem[y] > lx[x] + ly[y] - w[x][y]) 8 | rem[y] = lx[x] + ly[y] - w[x][y], remx[y] = x; 9 | } 10 | 11 | int kuhn_munkres(int n) { 12 | for(int i = 0; i < n; i++) mx[i] = my[i] = -1, lx[i] = ly[i] = 0; 13 | for(int i = 0; i < n; i++) 14 | for(int j = 0; j < n; j++) 15 | ly[j] = max(ly[j], w[i][j]); 16 | 17 | for(int i = 0; i < n; i++) { 18 | memset(s, 0, sizeof s); memset(rem, 0x3f, sizeof rem); 19 | 20 | int st; 21 | for(st = 0; st < n; st++) if(mx[st] == -1) { add(st, n); break; } 22 | while(mx[st] == -1) { 23 | int miny = -1; 24 | for(int y = 0; y < n; y++) 25 | if(rem[y] != -INF && (miny == -1 || rem[miny] >= rem[y])) 26 | miny = y; 27 | 28 | if(rem[miny]) { 29 | for(int x = 0; x < n; x++) if(s[x]) lx[x] -= rem[miny]; 30 | for(int y = 0, d = rem[miny]; y < n; y++) 31 | if(rem[y] == -INF) ly[y] += d; else rem[y] -= d; 32 | } 33 | 34 | if(my[miny] == -1) { 35 | int cur = miny; 36 | while(remx[cur] != st) { 37 | int pmate = mx[remx[cur]]; 38 | my[cur] = remx[cur], mx[my[cur]] = cur; 39 | my[pmate] = -1; cur = pmate; 40 | } 41 | my[cur] = remx[cur], mx[my[cur]] = cur; 42 | } else 43 | add(my[miny], n), rem[miny] = -INF; 44 | } 45 | } 46 | 47 | int ret = 0; 48 | for(int i = 0; i < n; i++) 49 | ret += w[i][mx[i]]; 50 | return ret; 51 | } 52 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/link_cut.cpp: -------------------------------------------------------------------------------- 1 | class splay { 2 | public: 3 | splay *sons[2], *up, *path_up; 4 | splay() : up(NULL), path_up(NULL) { 5 | sons[0] = sons[1] = NULL; 6 | } 7 | 8 | bool is_r(splay* n) { 9 | return n == sons[1]; 10 | } 11 | }; 12 | 13 | void rotate(splay* t, bool to_l) { 14 | splay* n = t->sons[to_l]; swap(t->path_up, n->path_up); 15 | t->sons[to_l] = n->sons[!to_l]; if(t->sons[to_l]) t->sons[to_l]->up = t; 16 | n->up = t->up; if(n->up) n->up->sons[n->up->is_r(t)] = n; 17 | n->sons[!to_l] = t; t->up = n; 18 | } 19 | 20 | void do_splay(splay* n) { 21 | for(splay* p; (p = n->up) != NULL; ) 22 | if(p->up == NULL) 23 | rotate(p, p->is_r(n)); 24 | else { 25 | bool dirp = p->is_r(n), dirg = p->up->is_r(p); 26 | if(dirp == dirg) 27 | rotate(p->up, dirg), rotate(p, dirp); 28 | else 29 | rotate(p, dirp), rotate(n->up, dirg); 30 | } 31 | } 32 | 33 | struct link_cut { 34 | splay* vtxs; 35 | link_cut(int numv) { vtxs = new splay[numv]; } 36 | ~link_cut() { delete[] vtxs; } 37 | 38 | void access(splay* ov) { 39 | for(splay *w = ov, *v = ov; w != NULL; v = w, w = w->path_up) { 40 | do_splay(w); 41 | if(w->sons[1]) w->sons[1]->path_up = w, w->sons[1]->up = NULL; 42 | if(w != v) w->sons[1] = v, v->up = w, v->path_up = NULL; 43 | else w->sons[1] = NULL; 44 | } 45 | do_splay(ov); 46 | } 47 | 48 | splay* find(int v) { 49 | splay* s = &vtxs[v]; 50 | access(s); while(s->sons[0]) s = s->sons[0]; do_splay(s); 51 | return s; 52 | } 53 | 54 | void link(int parent, int son) { 55 | access(&vtxs[son]); access(&vtxs[parent]); 56 | assert(vtxs[son].sons[0] == NULL); 57 | vtxs[son].sons[0] = &vtxs[parent]; 58 | vtxs[parent].up = &vtxs[son]; 59 | } 60 | 61 | void cut(int v) { 62 | access(&vtxs[v]); 63 | if(vtxs[v].sons[0]) vtxs[v].sons[0]->up = NULL; 64 | vtxs[v].sons[0] = NULL; 65 | } 66 | 67 | int lca(int v, int w) { 68 | access(&vtxs[v]); access(&vtxs[w]); do_splay(&vtxs[v]); 69 | if(vtxs[v].path_up == NULL) return v; 70 | return vtxs[v].path_up - vtxs; 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/graph/scc.cpp: -------------------------------------------------------------------------------- 1 | int lowest[MAXV], num[MAXV], visited[MAXV], comp[MAXV]; 2 | int prev_edge[MAXE], last_edge[MAXV], adj[MAXE], nedges; 3 | int cur_num, cur_comp; 4 | stack visiting; 5 | 6 | void t_init() { 7 | memset(last_edge, -1, sizeof last_edge); 8 | nedges = 0; 9 | } 10 | 11 | void t_edge(int v, int w) { 12 | prev_edge[nedges] = last_edge[v]; 13 | adj[nedges] = w; 14 | last_edge[v] = nedges++; 15 | } 16 | 17 | int tarjan_dfs(int v) { 18 | lowest[v] = num[v] = cur_num++; 19 | visiting.push(v); 20 | 21 | visited[v] = 1; 22 | for(int i = last_edge[v]; i != -1; i = prev_edge[i]) { 23 | int w = adj[i]; 24 | if(visited[w] == 0) lowest[v] = min(lowest[v], tarjan_dfs(w)); 25 | else if(visited[w] == 1) lowest[v] = min(lowest[v], num[w]); 26 | } 27 | 28 | if(lowest[v] == num[v]) { 29 | int last = -1; 30 | while(last != v) { 31 | comp[last = visiting.top()] = cur_comp; 32 | visited[last] = 2; 33 | visiting.pop(); 34 | } 35 | ++cur_comp; 36 | } 37 | 38 | return lowest[v]; 39 | } 40 | 41 | void tarjan_scc(int num_v = MAXV) { 42 | visiting = stack(); 43 | memset(visited, 0, sizeof visited); 44 | cur_num = cur_comp = 0; 45 | 46 | for(int i = 0; i < num_v; ++i) 47 | if(!visited[i]) 48 | tarjan_dfs(i); 49 | } 50 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/Makefile: -------------------------------------------------------------------------------- 1 | FILES = .crt.cpp.hash .frac.cpp.hash .lis.cpp.hash .simplex.cpp.hash .romberg.cpp.hash .polynomials.cpp.hash .floyd.cpp.hash .pollard.cpp.hash .miller_rabin.cpp.hash .karatsuba.cpp.hash .sieve.cpp.hash .fft.cpp.hash 2 | 3 | all: $(FILES) 4 | 5 | .PHONY: clean 6 | 7 | $(FILES): .%.hash: % 8 | ../gen_hash.sh $< $@ 9 | 10 | clean: 11 | rm -f $(FILES) 12 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/crt.cpp: -------------------------------------------------------------------------------- 1 | struct t { 2 | long long a, b; int g; 3 | t(long long a, long long b, int g) : a(a), b(b), g(g) { } 4 | t swap() { return t(b, a, g); } 5 | }; 6 | 7 | t egcd(int p, int q) { 8 | if(q == 0) return t(1, 0, p); 9 | 10 | t t2 = egcd(q, p % q); 11 | t2.a -= t2.b * (p/q); 12 | return t2.swap(); 13 | } 14 | 15 | int crt(int a, int p, int b, int q) { 16 | t t2 = egcd(p, q); t2.a %= p*q; t2.b %= p*q; 17 | assert(t2.g == 1); 18 | int ret = ((b * t2.a)%(p*q) * p + (a * t2.b)%(p*q) * q) % (p*q); 19 | return ret >= 0 ? ret : ret + p*q; 20 | } 21 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/fft.cpp: -------------------------------------------------------------------------------- 1 | typedef complex pt; 2 | pt tmp[1<<20]; 3 | 4 | void fft(pt *in, int sz, bool inv = false) { 5 | if(sz == 1) return; 6 | for(int i = 0; i < sz; i++) 7 | tmp[i] = in[i]; 8 | 9 | sz /= 2; 10 | pt *even = in, *odd = in + sz; 11 | for(int i = 0; i < 2*sz; i++) 12 | if(i&1) odd[i/2] = tmp[i]; 13 | else even[i/2] = tmp[i]; 14 | 15 | fft(even, sz, inv); 16 | fft(odd, sz, inv); 17 | 18 | long double p = (inv ? 1 : -1) * acosl(-1)/sz; 19 | for(int i = 0; i < sz; i++) { 20 | pt conv = pt(cosl(i*p), sinl(i*p)) * odd[i]; 21 | tmp[i] = even[i] + conv; 22 | tmp[i+sz] = even[i] - conv; 23 | } 24 | 25 | for(int i = 0; i < 2*sz; i++) 26 | in[i] = tmp[i]; 27 | } 28 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/floyd.cpp: -------------------------------------------------------------------------------- 1 | pair floyd(int x0) { 2 | int t = f(x0), h = f(f(x0)), start = 0, length = 1; 3 | while(t != h) 4 | t = f(t), h = f(f(h)); 5 | 6 | h = t; t = x0; 7 | while(t != h) 8 | t = f(t), h = f(h), ++start; 9 | 10 | h = f(t); 11 | while(t != h) 12 | h = f(h), ++length; 13 | 14 | return make_pair(start, length); 15 | } 16 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/frac.cpp: -------------------------------------------------------------------------------- 1 | struct frac { 2 | long long num, den; 3 | frac(long long num = 0, long long den = 1) { set_val(num, den); } 4 | 5 | void set_val(long long _num, long long _den) { 6 | num = _num/__gcd(_num, _den); 7 | den = _den/__gcd(_num, _den); 8 | if(den < 0) { num *= -1; den *= -1; } 9 | } 10 | 11 | void operator*=(frac f) { set_val(num * f.num, den * f.den); } 12 | void operator+=(frac f) { set_val(num * f.den + f.num * den, den * f.den); } 13 | void operator-=(frac f) { set_val(num * f.den - f.num * den, den * f.den); } 14 | void operator/=(frac f) { set_val(num * f.den, den * f.num); } 15 | }; 16 | 17 | bool operator==(frac a, frac b) { return a.num * b.den == b.num * a.den; } 18 | bool operator!=(frac a, frac b) { return !(a == b); } 19 | bool operator<(frac a, frac b) { return a.num * b.den < b.num * a.den; } 20 | bool operator<=(frac a, frac b) { return (a == b) || (a < b); } 21 | bool operator>(frac a, frac b) { return !(a <= b); } 22 | bool operator>=(frac a, frac b) { return !(a < b); } 23 | frac operator/(frac a, frac b) { frac ret = a; ret /= b; return ret; } 24 | frac operator*(frac a, frac b) { frac ret = a; ret *= b; return ret; } 25 | frac operator+(frac a, frac b) { frac ret = a; ret += b; return ret; } 26 | frac operator-(frac a, frac b) { frac ret = a; ret -= b; return ret; } 27 | frac operator-(frac f) { return 0 - f; } 28 | 29 | std::ostream& operator<<(std::ostream& o, const frac f) { 30 | o << f.num << "/" << f.den; 31 | return o; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/karatsuba.cpp: -------------------------------------------------------------------------------- 1 | typedef vector poly; 2 | 3 | poly mult(const poly& p, const poly& q) { 4 | int sz = p.size(), half = sz/2; 5 | assert(sz == q.size() && !(sz&(sz-1))); 6 | 7 | if(sz <= 64) { 8 | poly ret(2*sz); 9 | for(int i = 0; i < sz; i++) 10 | for(int j = 0; j < sz; j++) 11 | ret[i+j] += p[i] * q[j]; 12 | return ret; 13 | } 14 | 15 | poly p1(p.begin(), p.begin() + half), p2(p.begin() + half, p.end()); 16 | poly q1(q.begin(), q.begin() + half), q2(q.begin() + half, q.end()); 17 | poly p1p2(half), q1q2(half); 18 | for(int i = 0; i < half; i++) 19 | p1p2[i] = p1[i] + p2[i], q1q2[i] = q1[i] + q2[i]; 20 | 21 | poly low = mult(p1, q1), high = mult(p2, q2), mid = mult(p1p2, q1q2); 22 | for(int i = 0; i < sz; i++) 23 | mid[i] -= high[i] + low[i]; 24 | 25 | low.resize(2*sz); 26 | for(int i = 0; i < sz; i++) 27 | low[i+half] += mid[i], low[i+sz] += high[i]; 28 | 29 | return low; 30 | } 31 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/lis.cpp: -------------------------------------------------------------------------------- 1 | vector lis(vector& seq) { 2 | int smallest_end[seq.size()+1], prev[seq.size()]; 3 | smallest_end[1] = 0; 4 | 5 | int sz = 1; 6 | for(int i = 1; i < seq.size(); ++i) { 7 | int lo = 0, hi = sz; 8 | while(lo < hi) { 9 | int mid = (lo + hi + 1)/2; 10 | if(seq[smallest_end[mid]] <= seq[i]) 11 | lo = mid; 12 | else 13 | hi = mid - 1; 14 | } 15 | 16 | prev[i] = smallest_end[lo]; 17 | if(lo == sz) 18 | smallest_end[++sz] = i; 19 | else if(seq[i] < seq[smallest_end[lo+1]]) 20 | smallest_end[lo+1] = i; 21 | } 22 | 23 | vector ret; 24 | for(int cur = smallest_end[sz]; sz > 0; cur = prev[cur], --sz) 25 | ret.push_back(seq[cur]); 26 | reverse(ret.begin(), ret.end()); 27 | 28 | return ret; 29 | } 30 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/miller_rabin.cpp: -------------------------------------------------------------------------------- 1 | int fastpow(int base, int d, int n) { 2 | int ret = 1; 3 | for(long long pow = base; d > 0; d >>= 1, pow = (pow * pow) % n) 4 | if(d & 1) 5 | ret = (ret * pow) % n; 6 | return ret; 7 | } 8 | 9 | bool miller_rabin(int n, int base) { 10 | if(n <= 1) return false; 11 | if(n % 2 == 0) return n == 2; 12 | 13 | int s = 0, d = n - 1; 14 | while(d % 2 == 0) d /= 2, ++s; 15 | 16 | int base_d = fastpow(base, d, n); 17 | if(base_d == 1) return true; 18 | int base_2r = base_d; 19 | 20 | for(int i = 0; i < s; ++i) { 21 | if(base_2r == 1) return false; 22 | if(base_2r == n - 1) return true; 23 | base_2r = (long long)base_2r * base_2r % n; 24 | } 25 | 26 | return false; 27 | } 28 | 29 | bool isprime(int n) { 30 | if(n == 2 || n == 7 || n == 61) return true; 31 | return miller_rabin(n, 2) && miller_rabin(n, 7) && miller_rabin(n, 61); 32 | } 33 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/pollard.cpp: -------------------------------------------------------------------------------- 1 | long long pollard_r, pollard_n; 2 | 3 | inline long long f(long long val) { return (val*val + pollard_r) % pollard_n; } 4 | inline long long myabs(long long a) { return a >= 0 ? a : -a; } 5 | 6 | long long pollard(long long n) { 7 | srand(unsigned(time(0))); 8 | pollard_n = n; 9 | 10 | long long d = 1; 11 | do { 12 | d = 1; 13 | pollard_r = rand() % n; 14 | 15 | long long x = 2, y = 2; 16 | while(d == 1) 17 | x = f(x), y = f(f(y)), d = __gcd(myabs(x-y), n); 18 | } while(d == n); 19 | 20 | return d; 21 | } 22 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/polynomials.cpp: -------------------------------------------------------------------------------- 1 | typedef complex cdouble; 2 | int cmp(cdouble x, cdouble y = 0) { 3 | return cmp(abs(x), abs(y)); 4 | } 5 | const int TAM = 200; 6 | struct poly { 7 | cdouble poly[TAM]; int n; 8 | poly(int n = 0): n(n) { memset(p, 0, sizeof(p)); } 9 | cdouble& operator [](int i) { return p[i]; } 10 | poly operator ~() { 11 | poly r(n-1); 12 | for (int i = 1; i <= n; i++) 13 | r[i-1] = p[i] * cdouble(i); 14 | return r; 15 | } 16 | pair ruffini(cdouble z) { 17 | if (n == 0) return make_pair(poly(), 0); 18 | poly r(n-1); 19 | for (int i = n; i > 0; i--) r[i-1] = r[i] * z + p[i]; 20 | return make_pair(r, r[0] * z + p[0]); 21 | } 22 | cdouble operator ()(cdouble z) { return ruffini(z).second; } 23 | cdouble find_one_root(cdouble x) { 24 | poly p0 = *this, p1 = ~p0, p2 = ~p1; 25 | int m = 1000; 26 | while (m--) { 27 | cdouble y0 = p0(x); 28 | if (cmp(y0) == 0) break; 29 | cdouble G = p1(x) / y0; 30 | cdouble H = G * G - p2(x) - y0; 31 | cdouble R = sqrt(cdouble(n-1) * (H * cdouble(n) - G * G)); 32 | cdouble D1 = G + R, D2 = G - R; 33 | cdouble a = cdouble(n) / (cmp(D1, D2) > 0 ? D1 : D2); 34 | x -= a; 35 | if (cmp(a) == 0) break; 36 | } 37 | return x; 38 | } 39 | vector roots() { 40 | poly q = *this; 41 | vector r; 42 | while (q.n > 1) { 43 | cdouble z(rand() / double(RAND_MAX), rand() / double(RAND_MAX)); 44 | z = q.find_one_root(z); z = find_one_root(z); 45 | q = q.ruffini(z).first; 46 | r.push_back(z); 47 | } 48 | return r; 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/romberg.cpp: -------------------------------------------------------------------------------- 1 | long double romberg(long double a, long double b, 2 | long double(*func)(long double)) { 3 | long double approx[2][25]; 4 | long double *cur=approx[1], *prev=approx[0]; 5 | 6 | prev[0] = 1/2.0 * (b-a) * (func(a) + func(b)); 7 | for(int it = 1; it < 25; ++it, swap(cur, prev)) { 8 | if(it > 1 && cmp(prev[it-1], prev[it-2]) == 0) 9 | return prev[it-1]; 10 | 11 | cur[0] = 1/2.0 * prev[0]; 12 | long double div = (b-a)/pow(2, it); 13 | for(long double sample = a + div; sample < b; sample += 2 * div) 14 | cur[0] += div * func(a + sample); 15 | 16 | for(int j = 1; j <= it; ++j) 17 | cur[j] = cur[j-1] + 1/(pow(4, it) - 1)*(cur[j-1] + prev[j-1]); 18 | } 19 | 20 | return prev[24]; 21 | } 22 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/math/sieve.cpp: -------------------------------------------------------------------------------- 1 | const unsigned MAX = 1000000020/60, MAX_S = sqrt(MAX/60); 2 | 3 | unsigned w[16] = {1, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 49, 53, 59}; 4 | unsigned short composite[MAX]; 5 | vector primes; 6 | 7 | void sieve() { 8 | unsigned mod[16][16], di[16][16], num; 9 | for(int i = 0; i < 16; i++) 10 | for(int j = 0; j < 16; j++) { 11 | di[i][j] = (w[i]*w[j])/60; 12 | mod[i][j] = lower_bound(w, w + 16, (w[i]*w[j])%60) - w; 13 | } 14 | 15 | primes.push_back(2); primes.push_back(3); primes.push_back(5); 16 | 17 | memset(composite, 0, sizeof composite); 18 | for(unsigned i = 0; i < MAX; i++) 19 | for(int j = (i==0); j < 16; j++) { 20 | if(composite[i] & (1< MAX_S) continue; 24 | for(unsigned k = i, done = false; !done; k++) 25 | for(int l = (k==0); l < 16 && !done; l++) { 26 | unsigned mult = k*num + i*w[l] + di[j][l]; 27 | if(mult >= MAX) done = true; 28 | else composite[mult] |= 1< VT; 4 | vector A; 5 | VT b,c,res; 6 | VI kt,N; 7 | int m; 8 | inline void pivot(int k,int l,int e){ 9 | int x=kt[l]; T p=A[l][e]; 10 | REP(i,k) A[l][i]/=p; b[l]/=p; N[e]=0; 11 | REP(i,m) if (i!=l) b[i]-=A[i][e]*b[l],A[i][x]=A[i][e]*-A[l][x]; 12 | REP(j,k) if (N[j]){ 13 | c[j]-=c[e]*A[l][j]; 14 | REP(i,m) if (i!=l) A[i][j]-=A[i][e]*A[l][j]; 15 | } 16 | kt[l]=e; N[x]=1; c[x]=c[e]*-A[l][x]; 17 | } 18 | 19 | VT doit(int k){ 20 | VT res; T best; 21 | while (1){ 22 | int e=-1,l=-1; REP(i,k) if (N[i] && c[i]>EPS) {e=i; break;} 23 | if (e==-1) break; 24 | REP(i,m) if (A[i][e]>EPS && (l==-1 || best>b[i]/A[i][e])) 25 | best=b[ l=i ]/A[i][e]; 26 | if (l==-1) /*ilimitado*/ return VT(); 27 | pivot(k,l,e); 28 | } 29 | res.resize(k,0); REP(i,m) res[kt[i]]=b[i]; 30 | return res; 31 | } 32 | 33 | VT simplex(vector &AA,VT &bb,VT &cc){ 34 | int n=AA[0].size(),k; 35 | m=AA.size(); k=n+m+1; kt.resize(m); b=bb; c=cc; c.resize(n+m); 36 | A=AA; REP(i,m){ A[i].resize(k); A[i][n+i]=1; A[i][k-1]=-1; kt[i]=n+i;} 37 | N=VI(k,1); REP(i,m) N[kt[i]]=0; 38 | int pos=min_element(ALL(b))-b.begin(); 39 | if (b[pos]<-EPS){ 40 | c=VT(k,0); c[k-1]=-1; pivot(k,pos,k-1); res=doit(k); 41 | if (res[k-1]>EPS) /*impossivel*/ return VT(); 42 | REP(i,m) if (kt[i]==k-1) 43 | REP(j,k-1) if (N[j] && (A[i][j]<-EPS || EPS > out; // num e tamanho do padrao 4 | //bool marc; // p/ decisao 5 | map lista; 6 | int next; // aponta para o proximo sufixo que tenha out.size > 0 7 | }; 8 | No arvore[1000003]; // quantida maxima de nos 9 | //bool encontrado[1005]; // quantidade maxima de padroes, p/ decisao 10 | int qtdNos, qtdPadroes; 11 | 12 | // Funcao para inicializar 13 | void inic() { 14 | arvore[0].fail = -1; 15 | arvore[0].lista.clear(); 16 | arvore[0].out.clear(); 17 | arvore[0].next = -1; 18 | qtdNos = 1; 19 | qtdPadroes = 0; 20 | //arvore[0].marc = false; // p/ decisao 21 | //memset(encontrado, false, sizeof(encontrado)); // p/ decisao 22 | } 23 | 24 | // Funcao para adicionar um padrao 25 | void adicionar(char *padrao) { 26 | int no = 0, len = 0; 27 | for (int i = 0 ; padrao[i] ; i++, len++) { 28 | if (arvore[no].lista.find(padrao[i]) == arvore[no].lista.end()) { 29 | arvore[qtdNos].lista.clear(); arvore[qtdNos].out.clear(); 30 | //arvore[qtdNos].marc = false; // p/ decisao 31 | arvore[no].lista[padrao[i]] = qtdNos; 32 | no = qtdNos++; 33 | } else no = arvore[no].lista[padrao[i]]; 34 | } 35 | arvore[no].out.push_back(pair(qtdPadroes++,len)); 36 | } 37 | 38 | // Ativar Aho-corasick, ajustando funcoes de falha 39 | void ativar() { 40 | int no,v,f,w; 41 | queue fila; 42 | for (map::iterator it = arvore[0].lista.begin(); 43 | it != arvore[0].lista.end() ; it++) { 44 | arvore[no = it->second].fail = 0; 45 | arvore[no].next = arvore[0].out.size() ? 0 : -1; 46 | fila.push(no); 47 | } 48 | while (!fila.empty()) { 49 | no = fila.front(); fila.pop(); 50 | for (map::iterator it=arvore[no].lista.begin(); 51 | it!=arvore[no].lista.end(); it++) { 52 | char c = it->first; 53 | v = it->second; 54 | fila.push(v); 55 | f = arvore[no].fail; 56 | while (arvore[f].lista.find(c) == arvore[f].lista.end()) { 57 | if (f == 0) { arvore[0].lista[c] = 0; break; } 58 | f = arvore[f].fail; 59 | } 60 | w = arvore[f].lista[c]; 61 | arvore[v].fail = w; 62 | arvore[v].next = arvore[w].out.size() ? w : arvore[w].next; 63 | } 64 | } 65 | } 66 | 67 | // Buscar padroes no aho-corasik 68 | void buscar(char *input) { 69 | int v, no = 0; 70 | for (int i = 0 ; input[i] ; i++) { 71 | while (arvore[no].lista.find(input[i]) == arvore[no].lista.end()) { 72 | if (no == 0) { arvore[0].lista[input[i]] = 0; break; } 73 | no = arvore[no].fail; 74 | } 75 | v = no = arvore[no].lista[input[i]]; 76 | // marcar os encontrados 77 | while (v != -1 /* && !arvore[v].marc */ ) { // p/ decisao 78 | //arvore[v].marc = true; // p/ decisao: nao continua a lista 79 | for (int k = 0 ; k < arvore[v].out.size() ; k++) { 80 | //encontrado[arvore[v].out[k].first] = true; // p/ decisao 81 | printf("Padrao %d na posicao %d\n", arvore[v].out[k].first, 82 | i-arvore[v].out[k].second+1); 83 | } 84 | v = arvore[v].next; 85 | } 86 | } 87 | // for (int i = 0 ; i < qtdPadroes ; i++) 88 | //printf("%s\n", encontrado[i]?"y":"n"); // p/ decisao 89 | } 90 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/string/aho_corasick_2.cpp: -------------------------------------------------------------------------------- 1 | int term[N]; map next[N]; int T[N]; int cnt = 1; 2 | void add(string s, int it){ 3 | int node = 0; 4 | f(i, 0, s.size()){ 5 | char c = s[i]; 6 | if(!next[node].count(c)) term[cnt] = 0, next[node][c] = cnt, cnt++; 7 | node = next[node][c]; 8 | } 9 | term[node] = 1 << it; 10 | } 11 | void aho(){ 12 | queue q; 13 | for(char c = 'a'; c <= 'z'; c++) 14 | if(next[0].count(c)) q.push(next[0][c]), T[next[0][c]] = 0; 15 | else next[0][c] = 0; 16 | 17 | while(!q.empty()){ 18 | int u = q.front(); q.pop(); 19 | for(char c = 'a'; c <= 'z'; c++) if(next[u].count(c)){ 20 | int v = next[u][c]; 21 | int x = T[u]; 22 | while(!next[x].count(c)) x = T[x]; 23 | x = next[x][c]; 24 | T[v] = x; 25 | q.push(v); 26 | term[v] |= term[x]; 27 | } 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/string/karkkainen.cpp: -------------------------------------------------------------------------------- 1 | bool k_cmp(int a1, int b1, int a2, int b2, int a3 = 0, int b3 = 0) { 2 | return a1 != b1 ? a1 < b1 : (a2 != b2 ? a2 < b2 : a3 < b3); 3 | } 4 | 5 | int bucket[MAXSZ+1], tmp[MAXSZ]; 6 | template void k_radix(T keys, int *in, int *out, 7 | int off, int n, int k) { 8 | memset(bucket, 0, sizeof(int) * (k+1)); 9 | 10 | for(int j = 0; j < n; j++) 11 | bucket[keys[in[j]+off]]++; 12 | for(int j = 0, sum = 0; j <= k; j++) 13 | sum += bucket[j], bucket[j] = sum - bucket[j]; 14 | for(int j = 0; j < n; j++) 15 | out[bucket[keys[in[j]+off]]++] = in[j]; 16 | } 17 | 18 | int m0[MAXSZ/3+1]; 19 | vector k_rec(const vector& v, int k) { 20 | int n = v.size()-3, sz = (n+2)/3, sz2 = sz + n/3; 21 | if(n < 2) return vector(n); 22 | 23 | vector sub(sz2+3); 24 | for(int i = 1, j = 0; j < sz2; i += i%3, j++) 25 | sub[j] = i; 26 | 27 | k_radix(v.begin(), &sub[0], tmp, 2, sz2, k); 28 | k_radix(v.begin(), tmp, &sub[0], 1, sz2, k); 29 | k_radix(v.begin(), &sub[0], tmp, 0, sz2, k); 30 | 31 | int last[3] = {-1, -1, -1}, unique = 0; 32 | for(int i = 0; i < sz2; i++) { 33 | bool diff = false; 34 | for(int j = 0; j < 3; last[j] = v[tmp[i]+j], j++) 35 | diff |= last[j] != v[tmp[i]+j]; 36 | unique += diff; 37 | 38 | if(tmp[i]%3 == 1) sub[tmp[i]/3] = unique; 39 | else sub[tmp[i]/3 + sz] = unique; 40 | } 41 | 42 | vector rec; 43 | if(unique < sz2) { 44 | rec = k_rec(sub, unique); 45 | rec.resize(sz2+sz); 46 | for(int i = 0; i < sz2; i++) sub[rec[i]] = i+1; 47 | } else { 48 | rec.resize(sz2+sz); 49 | for(int i = 0; i < sz2; i++) rec[sub[i]-1] = i; 50 | } 51 | 52 | for(int i = 0, j = 0; j < sz; i++) 53 | if(rec[i] < sz) 54 | tmp[j++] = 3*rec[i]; 55 | k_radix(v.begin(), tmp, m0, 0, sz, k); 56 | for(int i = 0; i < sz2; i++) 57 | rec[i] = rec[i] < sz ? 3*rec[i] + 1 : 3*(rec[i] - sz) + 2; 58 | 59 | int prec = sz2-1, p0 = sz-1, pret = sz2+sz-1; 60 | while(prec >= 0 && p0 >= 0) 61 | if(rec[prec]%3 == 1 && k_cmp(v[m0[p0]], v[rec[prec]], 62 | sub[m0[p0]/3], sub[rec[prec]/3+sz]) || 63 | rec[prec]%3 == 2 && k_cmp(v[m0[p0]], v[rec[prec]], 64 | v[m0[p0]+1], v[rec[prec]+1], 65 | sub[m0[p0]/3+sz], sub[rec[prec]/3+1])) 66 | rec[pret--] = rec[prec--]; 67 | else 68 | rec[pret--] = m0[p0--]; 69 | if(p0 >= 0) memcpy(&rec[0], m0, sizeof(int) * (p0+1)); 70 | 71 | if(n%3==1) rec.erase(rec.begin()); 72 | return rec; 73 | } 74 | 75 | vector karkkainen(const string& s) { 76 | int n = s.size(), cnt = 1; 77 | vector v(n + 3); 78 | 79 | for(int i = 0; i < n; i++) v[i] = i; 80 | k_radix(s.begin(), &v[0], tmp, 0, n, 256); 81 | for(int i = 0; i < n; cnt += (i+1 < n && s[tmp[i+1]] != s[tmp[i]]), i++) 82 | v[tmp[i]] = cnt; 83 | 84 | return k_rec(v, cnt); 85 | } 86 | 87 | vector lcp(const string& s, const vector& sa) { 88 | int n = sa.size(); 89 | vector prm(n), ans(n-1); 90 | for(int i = 0; i < n; i++) prm[sa[i]] = i; 91 | 92 | for(int h = 0, i = 0; i < n; i++) 93 | if(prm[i]) { 94 | int j = sa[prm[i]-1], ij = max(i, j); 95 | while(ij + h < n && s[i+h] == s[j+h]) h++; 96 | ans[prm[i]-1] = h; 97 | if(h) h--; 98 | } 99 | return ans; 100 | } 101 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/string/manacher.cpp: -------------------------------------------------------------------------------- 1 | vector manacher(const string& s) { 2 | string s2 = "#"; 3 | for(unsigned int i = 0; i < s.size(); i++) 4 | s2 += s[i], s2 += '#'; 5 | 6 | int c = 1, sz = (int)s2.size(), j; 7 | vector ans(sz); 8 | while(c < sz) { 9 | while(c > ans[c] && c+ans[c]+1 < sz && s2[c-ans[c]-1] == s2[c+ans[c]+1]) 10 | ans[c]++; 11 | 12 | j = 1; 13 | while(c+j < sz && j < ans[c]-ans[c-j]) 14 | ans[c+j] = ans[c-j], j++; 15 | if(c+j < sz) 16 | ans[c+j] = ans[c]-j; 17 | c += j; 18 | } 19 | 20 | return ans; 21 | } 22 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/string/morris_pratt.cpp: -------------------------------------------------------------------------------- 1 | int pi[MAXSZ], res[MAXSZ], nres; 2 | 3 | void morris_pratt(string text, string pattern) { 4 | nres = 0; 5 | pi[0] = -1; 6 | for(int i = 1; i < pattern.size(); ++i) { 7 | pi[i] = pi[i-1]; 8 | while(pi[i] >= 0 && pattern[pi[i] + 1] != pattern[i]) 9 | pi[i] = pi[pi[i]]; 10 | if(pattern[pi[i] + 1] == pattern[i]) ++pi[i]; 11 | } 12 | 13 | int k = -1; //k + 1 eh o tamanho do match atual 14 | for(int i = 0; i < text.size(); ++i) { 15 | while(k >= 0 && pattern[k + 1] != text[i]) 16 | k = pi[k]; 17 | if(pattern[k + 1] == text[i]) ++k; 18 | if(k + 1 == pattern.size()) { 19 | res[nres++] = i - k; 20 | k = pi[k]; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/structures/Makefile: -------------------------------------------------------------------------------- 1 | FILES = .heap.cpp.hash .treap.cpp.hash .bignum.cpp.hash 2 | 3 | all: $(FILES) 4 | 5 | .PHONY: clean 6 | 7 | $(FILES): .%.hash: % 8 | ../gen_hash.sh $< $@ 9 | 10 | clean: 11 | rm -f $(FILES) 12 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/structures/heap.cpp: -------------------------------------------------------------------------------- 1 | struct heap { 2 | int heap[MAXV][2], v2n[MAXV]; 3 | int size; 4 | 5 | void init(int sz) __attribute__((always_inline)) { 6 | memset(v2n, -1, sizeof(int) * sz); 7 | size = 0; 8 | } 9 | 10 | void swap(int& a, int& b) __attribute__((always_inline)) { 11 | int temp = a; 12 | a = b; 13 | b = temp; 14 | } 15 | 16 | void s(int a, int b) __attribute__((always_inline)) { 17 | swap(v2n[heap[a][1]], v2n[heap[b][1]]); 18 | swap(heap[a][0], heap[b][0]); 19 | swap(heap[a][1], heap[b][1]); 20 | } 21 | 22 | int extract_min() { 23 | int ret = heap[0][1]; 24 | s(0, --size); 25 | 26 | int cur = 0, next = 2; 27 | while(next < size) { 28 | if(heap[next][0] > heap[next - 1][0]) 29 | next--; 30 | if(heap[next][0] >= heap[cur][0]) 31 | break; 32 | 33 | s(next, cur); 34 | cur = next; 35 | next = 2*cur + 2; 36 | } 37 | if(next == size && heap[next - 1][0] < heap[cur][0]) 38 | s(next - 1, cur); 39 | 40 | return ret; 41 | } 42 | 43 | void decrease_key(int vertex, int new_value) __attribute__((always_inline)) 44 | { 45 | if(v2n[vertex] == -1) { 46 | v2n[vertex] = size; 47 | heap[size++][1] = vertex; 48 | } 49 | 50 | heap[v2n[vertex]][0] = new_value; 51 | 52 | int cur = v2n[vertex]; 53 | while(cur >= 1) { 54 | int parent = (cur - 1)/2; 55 | if(new_value >= heap[parent][0]) 56 | break; 57 | 58 | s(cur, parent); 59 | cur = parent; 60 | } 61 | } 62 | }; 63 | 64 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/structures/treap.cpp: -------------------------------------------------------------------------------- 1 | typedef int TYPE; 2 | 3 | class treap { 4 | public: 5 | treap *left, *right; 6 | int priority, sons; 7 | TYPE value; 8 | 9 | treap(TYPE value) : left(NULL), right(NULL), value(value), sons(0) { 10 | priority = rand(); 11 | } 12 | 13 | ~treap() { 14 | if(left) delete left; 15 | if(right) delete right; 16 | } 17 | }; 18 | 19 | treap* find(treap* t, TYPE val) { 20 | if(!t) return NULL; 21 | if(val == t->value) return t; 22 | 23 | if(val < t->value) return find(t->left, val); 24 | if(val > t->value) return find(t->right, val); 25 | } 26 | 27 | void rotate_to_right(treap* &t) { 28 | treap* n = t->left; 29 | t->left = n->right; 30 | n->right = t; 31 | t = n; 32 | } 33 | 34 | void rotate_to_left(treap* &t) { 35 | treap* n = t->right; 36 | t->right = n->left; 37 | n->left = t; 38 | t = n; 39 | } 40 | 41 | void fix_augment(treap* t) { 42 | if(!t) return; 43 | t->sons = (t->left ? t->left->sons + 1 : 0) + 44 | (t->right ? t->right->sons + 1 : 0); 45 | } 46 | 47 | void insert(treap* &t, TYPE val) { 48 | if(!t) 49 | t = new treap(val); 50 | else 51 | insert(val <= t->value ? t->left : t->right, val); 52 | 53 | if(t->left && t->left->priority > t->priority) 54 | rotate_to_right(t); 55 | else if(t->right && t->right->priority > t->priority) 56 | rotate_to_left(t); 57 | 58 | fix_augment(t->left); fix_augment(t->right); fix_augment(t); 59 | } 60 | 61 | inline int p(treap* t) { 62 | return t ? t->priority : -1; 63 | } 64 | 65 | void erase(treap* &t, TYPE val) { 66 | if(!t) return; 67 | 68 | if(t->value != val) 69 | erase(val < t->value ? t->left : t->right, val); 70 | else { 71 | if(!t->left && !t->right) 72 | delete t, t = NULL; 73 | else { 74 | p(t->left) < p(t->right) ? rotate_to_left(t) : rotate_to_right(t); 75 | erase(t, val); 76 | } 77 | } 78 | 79 | fix_augment(t->left); fix_augment(t->right); fix_augment(t); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/babel.cpp: -------------------------------------------------------------------------------- 1 | #define MAXE 100052 2 | #define MAXV 105000 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | #include "../structures/heap.cpp" 13 | #include "../graph/dijkstra_sparse_fast.cpp" 14 | 15 | map idiomas; int numIdiomas; 16 | int cod(string s) 17 | { 18 | if(idiomas.find(s) == idiomas.end()) idiomas[s] = numIdiomas++; 19 | return idiomas[s]; 20 | } 21 | 22 | struct triple 23 | { 24 | int orig, dest; char c; 25 | triple() { } 26 | triple(int orig, int dest, char c) : orig(orig), dest(dest), c(c) { } 27 | bool operator<(triple t) const 28 | { 29 | if(orig < t.orig) return true; 30 | if(orig == t.orig && dest < t.dest) return true; 31 | if(orig == t.orig && dest == t.dest && c < t.c) return true; 32 | return false; 33 | } 34 | }; 35 | 36 | int main() 37 | { 38 | int M; 39 | while(cin >> M && M != 0) 40 | { 41 | idiomas.clear(); numIdiomas = 0; 42 | d_init(); 43 | 44 | string origem, destino, palavra; 45 | cin >> origem >> destino; 46 | int corigem = cod(origem), cdestino = cod(destino); 47 | 48 | map entradas; 49 | for(int i = 0; i < M; i++) 50 | { 51 | cin >> origem >> destino >> palavra; 52 | int dorigem = cod(origem), ddestino = cod(destino); 53 | if(dorigem > ddestino) swap(dorigem, ddestino); 54 | 55 | if(entradas[triple(dorigem, ddestino, palavra[0])] == 0) 56 | entradas[triple(dorigem, ddestino, palavra[0])] = palavra.size(); 57 | else 58 | entradas[triple(dorigem, ddestino, palavra[0])] = min(entradas[triple(dorigem, ddestino, palavra[0])], (int)palavra.size()); 59 | } 60 | 61 | for(map::iterator it = entradas.begin(); it != entradas.end(); it++) 62 | { 63 | triple atual = (*it).first; 64 | for(int c = 0; c < 26; c++) 65 | if(c != atual.c - 'a') 66 | { 67 | d_edge(atual.orig*26 + c, atual.dest*26 + (atual.c - 'a'), (*it).second); 68 | d_edge(atual.dest*26 + c, atual.orig*26 + (atual.c - 'a'), (*it).second); 69 | } 70 | } 71 | 72 | int source = numIdiomas * 26, sink = numIdiomas * 26 + 1; 73 | for(int i = 0; i < 26; i++) 74 | { 75 | d_edge(source, corigem * 26 + i, 0); 76 | d_edge(cdestino * 26 + i, sink, 0); 77 | } 78 | 79 | dijkstra(source, numIdiomas * 26 + 2); 80 | if(dist[sink] >= 0x3f3f3f3f) cout << "impossivel" << endl; 81 | else cout << dist[sink] << endl; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/babel.sol: -------------------------------------------------------------------------------- 1 | 6 2 | 7 3 | 3 4 | 3 5 | 5 6 | impossivel 7 | 9 8 | 6 9 | 10 10 | 8 11 | impossivel 12 | 5 13 | 2 14 | impossivel 15 | 29 16 | 21 17 | impossivel 18 | 26 19 | impossivel 20 | 17 21 | 32 22 | impossivel 23 | 75222 24 | 68 25 | 130 26 | 126 27 | 211 28 | 141 29 | 149 30 | 141 31 | 141 32 | 141 33 | 127 34 | 77 35 | impossivel 36 | 2199 37 | 2199 38 | 2199 39 | 2199 40 | 2199 41 | 2199 42 | 2199 43 | 2199 44 | 2199 45 | 2199 46 | 4399 47 | 4399 48 | 4399 49 | 4399 50 | 4399 51 | 4399 52 | 4399 53 | 4399 54 | 4399 55 | 4399 56 | 1099 57 | 1099 58 | 1099 59 | 1099 60 | 1099 61 | 1099 62 | 1099 63 | 1099 64 | 1099 65 | 1099 66 | 12 67 | impossivel 68 | 5 69 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/babel_stl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #define MAXE 100052 11 | #define MAXV 105000 12 | 13 | 14 | #include "../graph/dijkstra_sparse_small.cpp" 15 | 16 | map idiomas; int numIdiomas; 17 | int cod(string s) 18 | { 19 | if(idiomas.find(s) == idiomas.end()) idiomas[s] = numIdiomas++; 20 | return idiomas[s]; 21 | } 22 | 23 | struct triple 24 | { 25 | int orig, dest; char c; 26 | triple() { } 27 | triple(int orig, int dest, char c) : orig(orig), dest(dest), c(c) { } 28 | bool operator<(triple t) const 29 | { 30 | if(orig < t.orig) return true; 31 | if(orig == t.orig && dest < t.dest) return true; 32 | if(orig == t.orig && dest == t.dest && c < t.c) return true; 33 | return false; 34 | } 35 | }; 36 | 37 | int main() 38 | { 39 | int M; 40 | while(cin >> M && M != 0) 41 | { 42 | idiomas.clear(); numIdiomas = 0; 43 | d_init(); 44 | 45 | string origem, destino, palavra; 46 | cin >> origem >> destino; 47 | int corigem = cod(origem), cdestino = cod(destino); 48 | 49 | map entradas; 50 | for(int i = 0; i < M; i++) 51 | { 52 | cin >> origem >> destino >> palavra; 53 | int dorigem = cod(origem), ddestino = cod(destino); 54 | if(dorigem > ddestino) swap(dorigem, ddestino); 55 | 56 | if(entradas[triple(dorigem, ddestino, palavra[0])] == 0) 57 | entradas[triple(dorigem, ddestino, palavra[0])] = palavra.size(); 58 | else 59 | entradas[triple(dorigem, ddestino, palavra[0])] = min(entradas[triple(dorigem, ddestino, palavra[0])], (int)palavra.size()); 60 | } 61 | 62 | for(map::iterator it = entradas.begin(); it != entradas.end(); it++) 63 | { 64 | triple atual = (*it).first; 65 | for(int c = 0; c < 26; c++) 66 | if(c != atual.c - 'a') 67 | { 68 | d_edge(atual.orig*26 + c, atual.dest*26 + (atual.c - 'a'), (*it).second); 69 | d_edge(atual.dest*26 + c, atual.orig*26 + (atual.c - 'a'), (*it).second); 70 | } 71 | } 72 | 73 | int source = numIdiomas * 26, sink = numIdiomas * 26 + 1; 74 | for(int i = 0; i < 26; i++) 75 | { 76 | d_edge(source, corigem * 26 + i, 0); 77 | d_edge(cdestino * 26 + i, sink, 0); 78 | } 79 | 80 | dijkstra(source, numIdiomas * 26 + 2); 81 | if(dist[sink] >= 0x3f3f3f3f) cout << "impossivel" << endl; 82 | else cout << dist[sink] << endl; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/babel_stl.sol: -------------------------------------------------------------------------------- 1 | 6 2 | 7 3 | 3 4 | 3 5 | 5 6 | impossivel 7 | 9 8 | 6 9 | 10 10 | 8 11 | impossivel 12 | 5 13 | 2 14 | impossivel 15 | 29 16 | 21 17 | impossivel 18 | 26 19 | impossivel 20 | 17 21 | 32 22 | impossivel 23 | 75222 24 | 68 25 | 130 26 | 126 27 | 211 28 | 141 29 | 149 30 | 141 31 | 141 32 | 141 33 | 127 34 | 77 35 | impossivel 36 | 2199 37 | 2199 38 | 2199 39 | 2199 40 | 2199 41 | 2199 42 | 2199 43 | 2199 44 | 2199 45 | 2199 46 | 4399 47 | 4399 48 | 4399 49 | 4399 50 | 4399 51 | 4399 52 | 4399 53 | 4399 54 | 4399 55 | 4399 56 | 1099 57 | 1099 58 | 1099 59 | 1099 60 | 1099 61 | 1099 62 | 1099 63 | 1099 64 | 1099 65 | 1099 66 | 12 67 | impossivel 68 | 5 69 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/marques.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | #define MAXV 500 9 | #define MAXE 500*500 10 | 11 | #include "../graph/edmonds_karp.cpp" 12 | 13 | int main() 14 | { 15 | int n; cin >> n; string str; 16 | for(int z = 0; z < n; z++) 17 | { 18 | ek_init(); 19 | 20 | int onibus, pessoas; cin >> pessoas >> onibus; 21 | map > bus2ind; int ind = 0; 22 | for(int i = 0; i < onibus; i++) 23 | { 24 | cin >> str; 25 | bus2ind[str].push_back(ind++); 26 | } 27 | 28 | for(int i = 0; i < pessoas; i++) 29 | { 30 | int k; cin >> k; 31 | ek_edge(0, i + 1, 1); 32 | for(int j = 0; j < k; j++) 33 | { 34 | cin >> str; 35 | for(int l = 0; l < (int)bus2ind[str].size(); l++) 36 | ek_edge(i + 1, pessoas + 1 + bus2ind[str][l], 1); 37 | } 38 | } 39 | 40 | for(int i = 0; i < onibus; i++) 41 | ek_edge(pessoas + 1 + i, pessoas + onibus + 1, 1); 42 | 43 | int cur_flow = 0; 44 | for(int i = 1; i <= 100; i++) 45 | { 46 | for(int j = 0; j < onibus; j++) 47 | cap[last_edge[pessoas + 1 + j]] = i; 48 | 49 | cur_flow += edmonds_karp(0, pessoas + onibus + 1, pessoas + onibus + 2); 50 | if(cur_flow == pessoas) 51 | { 52 | cout << i << endl; 53 | break; 54 | } 55 | } 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/marques.sol: -------------------------------------------------------------------------------- 1 | 2 2 | 1 3 | 4 4 | 1 5 | 1 6 | 4 7 | 1 8 | 1 9 | 1 10 | 1 11 | 1 12 | 5 13 | 4 14 | 1 15 | 1 16 | 1 17 | 1 18 | 1 19 | 4 20 | 1 21 | 1 22 | 2 23 | 2 24 | 2 25 | 2 26 | 1 27 | 1 28 | 1 29 | 2 30 | 1 31 | 1 32 | 1 33 | 3 34 | 1 35 | 1 36 | 2 37 | 1 38 | 1 39 | 2 40 | 1 41 | 1 42 | 1 43 | 1 44 | 1 45 | 1 46 | 1 47 | 1 48 | 1 49 | 1 50 | 1 51 | 1 52 | 1 53 | 3 54 | 1 55 | 1 56 | 1 57 | 1 58 | 1 59 | 1 60 | 1 61 | 1 62 | 1 63 | 1 64 | 12 65 | 12 66 | 83 67 | 13 68 | 52 69 | 18 70 | 14 71 | 20 72 | 12 73 | 19 74 | 16 75 | 20 76 | 36 77 | 47 78 | 21 79 | 20 80 | 18 81 | 100 82 | 24 83 | 26 84 | 16 85 | 11 86 | 18 87 | 11 88 | 18 89 | 82 90 | 25 91 | 21 92 | 14 93 | 22 94 | 22 95 | 23 96 | 15 97 | 46 98 | 21 99 | 42 100 | 16 101 | 31 102 | 84 103 | 67 104 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/run_tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, subprocess, os; 4 | 5 | testlist = file('test_list', 'r'); 6 | 7 | for test in testlist: 8 | test = test.rstrip('\n'); 9 | sys.stdout.write('Executando teste {0}... '.format(test)); 10 | sys.stdout.flush(); 11 | 12 | if subprocess.call(['g++', '-o' + test, test + '.cpp']): 13 | print 'Erro de compilacao do programa {0}!'.format(test); 14 | break; 15 | 16 | p = subprocess.Popen('./' + test + ' < ' + test + '.in > ' + test + '.out', shell=True); 17 | os.waitpid(p.pid, 0); 18 | 19 | if subprocess.call(['diff', '-u', test + '.out', test + '.sol']): 20 | print 'Erro no teste do programa {0}!'.format(test); 21 | break; 22 | print 'OK!' 23 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | test_cpp() { 4 | echo "Testando "$1"..." 5 | if (g++ -o $1.bin $1.cpp -Wall -pedantic -lm -g) then 6 | if (./$1.bin < $1.in > $1.out) then 7 | diff -u $1.out $1.sol 8 | rm -f $1.out 9 | rm -f $1.bin 10 | echo $1": OK!" 11 | else 12 | echo $1": Programa não roda corretamente!" 13 | fi 14 | else 15 | echo $1": Erro de compilação!" 16 | fi 17 | } 18 | 19 | for i in *.cpp; do 20 | test_cpp `basename $i .cpp` 21 | echo 22 | done 23 | 24 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/test_coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cat *.cpp | egrep '#include *\"\.\.' | sed "s/^ *#include \"\.\.\/\(.*\)\"/\1/" 4 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tests/test_list: -------------------------------------------------------------------------------- 1 | babel 2 | babel_stl 3 | marques 4 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tex/Makefile: -------------------------------------------------------------------------------- 1 | biblioteca.pdf: 2 | pdflatex biblioteca.tex 3 | pdflatex biblioteca.tex 4 | 5 | docs.pt_BR.pdf: 6 | pdflatex docs.pt_BR.tex 7 | 8 | .PHONY: clean biblioteca.pdf 9 | 10 | clean: 11 | rm -f biblioteca.pdf biblioteca.log biblioteca.aux biblioteca.toc \ 12 | docs.pt_BR.pdf docs.pt_BR.log docs.pt_BR.aux docs.pt_BR.toc 13 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tex/biblioteca.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/anuncieaqui-biblioteca/tex/biblioteca.pdf -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tex/docs.pt_BR.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/anuncieaqui-biblioteca/tex/docs.pt_BR.pdf -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tex/docs.pt_BR.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper]{amsart} 2 | 3 | \usepackage{amsmath} 4 | \usepackage{amssymb} 5 | \usepackage{courier} 6 | \usepackage{fancyhdr} 7 | \usepackage[pdftex]{geometry} 8 | \usepackage[utf8]{inputenc} 9 | \usepackage{listings} 10 | \usepackage{multicol} 11 | 12 | \lstset{language=C++} 13 | \lstset{columns=fullflexible} 14 | \lstset{basicstyle=\scriptsize\ttfamily} 15 | \lstset{showspaces=false} 16 | 17 | \geometry{landscape} 18 | \setlength{\topmargin}{-0.25in} 19 | \setlength{\oddsidemargin}{0in} 20 | \setlength{\evensidemargin}{0in} 21 | \setlength{\columnsep}{1in} 22 | \setlength{\columnseprule}{0.2pt} 23 | \textwidth 9.5in 24 | 25 | \pagestyle{fancy} 26 | \lhead{Universidade Federal de Sergipe} 27 | \chead{} 28 | \rhead{\thepage} 29 | \lfoot{} 30 | \cfoot{} 31 | \rfoot{} 32 | 33 | \newcommand\lsiting[4]{ 34 | \begin{multicols}{2} 35 | [\subsection{#2}{Hash: \input{#3/.#4.hash}}\ ] 36 | \lstinputlisting[language=#1]{#3/#4} 37 | \end{multicols} 38 | } 39 | 40 | \newcommand{\stirlingfirst}[2]{\genfrac{[}{]}{0pt}{}{#1}{#2}} 41 | \newcommand{\stirlingsecond}[2]{\genfrac{\{}{\}}{0pt}{}{#1}{#2}} 42 | 43 | \begin{document} 44 | \thispagestyle{fancy} 45 | \begin{center} 46 | \Huge\textsc{ACM ICPC Team Reference Documentation} 47 | 48 | \ 49 | 50 | \huge Team Anuncie Aqui \\ Universidade Federal de Sergipe 51 | 52 | \ 53 | 54 | \end{center} 55 | 56 | \addtocontents{toc}{\protect\setcounter{tocdepth}{1}} 57 | \section{Configuration files and scripts} 58 | 59 | \begin{itemize} 60 | \item Arquivos de configuração do \texttt{emacs} e \texttt{vim}. 61 | \item Script para calcular o hash de código digitado. 62 | \item Template de solução com todos os includes. 63 | \end{itemize} 64 | 65 | \addtocontents{toc}{\protect\setcounter{tocdepth}{2}} 66 | \section{Graph algorithms} 67 | \subsection{Tarjan's SCC algorithm} 68 | \subsection{Dinic's maximum flow algorithm} 69 | \subsection{Successive shortest paths mincost maxflow algorithm} 70 | \subsection{Gabow's general matching algorithm} 71 | 72 | \section{Math} 73 | \subsection{Fractions} 74 | \subsection{Chinese remainder theorem} 75 | \subsection{Longest increasing subsequence} 76 | \subsection{Simplex (Warsaw University)} 77 | \subsection{Romberg's method} 78 | \subsection{Floyd's cycle detection algorithm} 79 | \subsection{Pollard's rho algorithm} 80 | \subsection{Miller-Rabin's algorithm} 81 | \subsection{Karatsuba's algorithm} 82 | \subsection{Polynomials (PUC-Rio)} 83 | 84 | \section{Geometry} 85 | \subsection{Point class} 86 | \subsection{Intersection primitives} 87 | \subsection{Polygon primitives} 88 | \subsection{Miscellaneous primitives} 89 | \subsection{Smallest enclosing circle} 90 | \subsection{Convex hull} 91 | \subsection{Closest pair of points} 92 | \subsection{Kd-tree} 93 | \subsection{Range tree} 94 | 95 | \section{Data structures} 96 | \subsection{Treap} 97 | \subsection{Heap} 98 | \subsection{Big numbers (PUC-Rio)} 99 | 100 | \section{String algorithms} 101 | \subsection{Kärkkäinen-Sanders' suffix array algorithm} 102 | \subsection{Morris-Pratt's algorithm} 103 | \subsection{Aho-Corasick's algorithm (UFPE)} 104 | 105 | \enlargethispage*{\baselineskip} 106 | \pagebreak 107 | 108 | \enlargethispage*{\baselineskip} 109 | \begin{center} 110 | \Huge\textsc{ACM ICPC Team Reference Documentation - Contents} 111 | 112 | \vspace{0.35cm} 113 | 114 | \huge Team Anuncie Aqui \\ Universidade Federal de Sergipe 115 | 116 | \vspace{0.35cm} 117 | 118 | \end{center} 119 | 120 | \begin{multicols}{2} 121 | \tableofcontents 122 | \end{multicols} 123 | \end{document} 124 | -------------------------------------------------------------------------------- /other/anuncieaqui-biblioteca/tex/mistakes.tex: -------------------------------------------------------------------------------- 1 | General strategy hints: 2 | \begin{enumerate} 3 | \item Everyone should have read every problem by the end of the second hour of competition. 4 | \item \textbf{In the last hour, only one question should be attempted at once.} 5 | \item Always use vectors instead of arrays in the single dimensional case. Use vectors instead of arrays in the bidimensional case if the outermost dimension is not too big. This allows for better debugging. 6 | \end{enumerate} 7 | 8 | When thinking (before coding): 9 | \begin{enumerate} 10 | \item \textbf{Be organized!} 11 | \item Don't touch the computer unless the solution is done, including implementation details: avoid thinking too much at the computer. \textbf{Time spent on paper detailing a solution is time well spent.} 12 | \item A corollary to the above: \textbf{Don't touch the computer if you doubt your idea}. 13 | \end{enumerate} 14 | 15 | In case you have no solution ideas: 16 | \begin{enumerate} 17 | \item (Include tricks from Pólya here) 18 | \end{enumerate} 19 | 20 | In case of Wrong Answer: 21 | \begin{enumerate} 22 | \item Make sure the algorithm is correct (i.e. \textbf{sketch a proof of correctness}) as soon as possible. Take your time and check it carefully. \textbf{If you're sure the idea is correct, make sure you don't second-guess it} when checking for bugs, even if an implementation bug is nowhere to be found. 23 | \item If the code uses vectors (c.f. general strategy hints), add \#define \_GLIBCXX\_DEBUG at the very beginning of the source code and submit it again. A runtime error means out-of-bounds array access or other STL misuse. 24 | \item Debug on paper, and don't go back to the computer for every bug you find: \textbf{check the whole solution at least once more after finding each new bug.} 25 | \item Think of tricky test cases. 26 | \item Read the problem again. For every constraint found, check the printed source code. 27 | \item If you can't find any bug in five minutes, \textbf{go to the bathroom}. If you still can't find the bug, \textbf{go to another problem and come back to the wrong solution later}. Debugging a single program for too long leads to finding a lot of false bugs and makes it easy to overlook simple mistakes. 28 | \end{enumerate} 29 | 30 | In case of Runtime Error: 31 | \begin{enumerate} 32 | \item Check divisions and modulo operations. 33 | \item Check array indices (both in declarations and in accesses). 34 | \item Check for infinite recursion. 35 | \end{enumerate} 36 | -------------------------------------------------------------------------------- /other/biblioteca.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/biblioteca.pdf -------------------------------------------------------------------------------- /other/bundle/all.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/bundle/all.pdf -------------------------------------------------------------------------------- /other/bundle/centroids.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/bundle/centroids.pdf -------------------------------------------------------------------------------- /other/bundle/codigos_sueltos.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/bundle/codigos_sueltos.pdf -------------------------------------------------------------------------------- /other/bundle/manual.pdf: -------------------------------------------------------------------------------- 1 | ../../manual.pdf -------------------------------------------------------------------------------- /other/bundle/notebook_fidel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/bundle/notebook_fidel.pdf -------------------------------------------------------------------------------- /other/bundle/notebook_mauricio.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/bundle/notebook_mauricio.pdf -------------------------------------------------------------------------------- /other/bundle/notebook_uniandes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/bundle/notebook_uniandes.pdf -------------------------------------------------------------------------------- /other/bundle/notebook_walter.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/bundle/notebook_walter.pdf -------------------------------------------------------------------------------- /other/centroids.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/centroids.pdf -------------------------------------------------------------------------------- /other/codigos_sueltos/MonsterTrap_Gaizka.java.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/codigos_sueltos/MonsterTrap_Gaizka.java.pdf -------------------------------------------------------------------------------- /other/codigos_sueltos/all.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/codigos_sueltos/all.pdf -------------------------------------------------------------------------------- /other/codigos_sueltos/anas_flow.cpp: -------------------------------------------------------------------------------- 1 | #include ... 2 | using namespace std; 3 | 4 | const int MAXN = 105; 5 | int g[2 * MAXN][2 * MAXN]; // 0 source, n+m+1 sink 6 | int flow[2 * MAXN][2 * MAXN]; 7 | int prev[2 * MAXN]; 8 | pair gophers [MAXN]; 9 | pair holes [MAXN]; 10 | 11 | 12 | bool canReach(int i, int j, double max_dist){ 13 | double x1 = gophers[i].first; double y1 = gophers[i].second; 14 | double x2 = holes[j].first; double y2 = holes[j].second; 15 | double d = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); 16 | if (d <= max_dist) return true; 17 | return false; 18 | } 19 | 20 | int max_flow(int s, int t){ 21 | int max_flow = 0; 22 | 23 | for (int i = s; i <= t; i++) 24 | for (int j = s; j <= t; j++) 25 | flow[i][j] = 0; 26 | 27 | while (true){ 28 | // Find path s to t 29 | for (int i = s; i <= t; i++) 30 | prev[i] = -1; 31 | 32 | queue q; 33 | q.push(s); 34 | prev[s] = -2; 35 | while (q.size() > 0){ 36 | int u = q.front(); q.pop(); 37 | if (u == t) break; 38 | for (int v = s; v <= t; v++){ 39 | if (prev[v] == -1 and g[u][v] - flow[u][v] > 0){ 40 | q.push(v); 41 | prev[v] = u; 42 | } 43 | } 44 | } 45 | if (prev[t] == -1) break; 46 | 47 | // Find bottlneck 48 | int curr = t; 49 | int bottleneck = 1 << 30; 50 | while (curr != s){ 51 | bottleneck = min(bottleneck, g[prev[curr]][curr] - flow[prev[curr]][curr]); 52 | curr = prev[curr]; 53 | } 54 | 55 | // Pump 56 | curr = t; 57 | while (curr != s){ 58 | flow[prev[curr]][curr] += bottleneck; 59 | flow[curr][prev[curr]] -= bottleneck; 60 | curr = prev[curr]; 61 | } 62 | 63 | // Add flow to answer 64 | max_flow += bottleneck; 65 | } 66 | 67 | return max_flow; 68 | } 69 | 70 | 71 | int main(){ 72 | int m, n, sec, vel; 73 | while (cin >> n >> m >> sec >> vel){ 74 | int s = 0; 75 | int t = n + m + 1; 76 | 77 | for (int i = 0; i <= t; i++) 78 | for (int j = 0; j <= t; j++) 79 | g[i][j] = 0; 80 | 81 | for (int i = 0; i < n; i++){ 82 | double x, y; 83 | cin >> x >> y; 84 | gophers[i] = make_pair(x, y); 85 | g[s][i + 1] = 1; 86 | } 87 | for (int i = 0; i < m; i++){ 88 | double x, y; 89 | cin >> x >> y; 90 | holes[i] = make_pair(x, y); 91 | g[i + 1 + n][t] = 1; 92 | } 93 | double max_dist = sec * vel; 94 | for (int i = 0; i < n; i++) 95 | for (int j = 0; j < m; j++) 96 | if (canReach(i, j, max_dist)) { 97 | g[i + 1][n + 1 + j] = 1; 98 | } 99 | cout << n - max_flow(s, t) << endl; 100 | } 101 | } -------------------------------------------------------------------------------- /other/codigos_sueltos/anas_flow.cpp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/codigos_sueltos/anas_flow.cpp.pdf -------------------------------------------------------------------------------- /other/codigos_sueltos/bridges.cpp: -------------------------------------------------------------------------------- 1 | // Encontrar puentes. 2 | #include ... 3 | using namespace std; 4 | 5 | const int MAXN = 10005; 6 | 7 | vector g[MAXN]; 8 | int p[MAXN], d[MAXN], low[MAXN], tick; 9 | 10 | int find(int x) { 11 | return p[x] == x ? x : p[x] = find(p[x]); 12 | } 13 | 14 | int link(int x, int y) { 15 | int a = find(x), b = find(y); 16 | if (a != b) { 17 | p[a] = b; 18 | } 19 | } 20 | 21 | // It's assumed that there is at most one edge 22 | // between two nodes. 23 | void dfs(int u, int parent = -1) { 24 | d[u] = low[u] = tick++; 25 | foreach(out, g[u]) { 26 | int v = *out; 27 | if (v == parent) continue; 28 | if (d[v] == -1) { 29 | dfs(v, u); 30 | low[u] = min(low[u], low[v]); 31 | } else { 32 | low[u] = min(low[u], d[v]); 33 | } 34 | 35 | if (low[v] > d[u]) { 36 | //printf("edge from %d to %d is a bridge\n", u + 1, v + 1); 37 | link(u, v); 38 | } 39 | } 40 | } 41 | 42 | int main(){ 43 | int n, e, q; 44 | while (scanf("%d %d %d", &n, &e, &q) == 3) { 45 | if (n == 0 and e == 0 and q == 0) break; 46 | for (int i = 0; i < n; ++i) { 47 | g[i].clear(); 48 | p[i] = i; 49 | d[i] = -1; 50 | } 51 | // read edges 52 | for (int i = 0; i < e; ++i) { 53 | int u, v; scanf("%d %d", &u, &v); 54 | u--, v--; 55 | g[u].push_back(v); 56 | g[v].push_back(u); 57 | } 58 | 59 | tick = 0; 60 | for (int i = 0; i < n; ++i) { 61 | if (d[i] == -1) dfs(i); 62 | } 63 | 64 | // read queries 65 | for (int i = 0; i < q; ++i) { 66 | int u, v; scanf("%d %d", &u, &v); 67 | u--, v--; 68 | 69 | if (find(u) == find(v)) { 70 | puts("Y"); 71 | } else { 72 | puts("N"); 73 | } 74 | } 75 | puts("-"); 76 | } 77 | return 0; 78 | } -------------------------------------------------------------------------------- /other/codigos_sueltos/bridges.cpp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/codigos_sueltos/bridges.cpp.pdf -------------------------------------------------------------------------------- /other/codigos_sueltos/heavy_light_decomposition.cpp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/codigos_sueltos/heavy_light_decomposition.cpp.pdf -------------------------------------------------------------------------------- /other/codigos_sueltos/mcmf_walter.cpp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/codigos_sueltos/mcmf_walter.cpp.pdf -------------------------------------------------------------------------------- /other/codigos_sueltos/star_war_filipe_martins.cpp: -------------------------------------------------------------------------------- 1 | // Star War de Filipe Martins 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | #define fr(a,b,c) for( int a = b ; a < c ; ++a ) 9 | #define rep(a,b) fr(a,0,b) 10 | #define db(x) cout << #x " == " << x << endl 11 | #define dbg db 12 | #define _ << ", " << 13 | 14 | #define EPS 1e-7 15 | int comp(double x, double y) { 16 | if( fabs(x-y) < EPS ) return 0; 17 | return x < y ? -1 : 1; 18 | } 19 | 20 | struct P{ 21 | double x,y,z; 22 | P() {} 23 | P(double x, double y, double z): x(x), y(y), z(z) {} 24 | 25 | P operator+(P b) { return P(x+b.x, y+b.y, z+b.z); } 26 | P operator-() { return P(-x,-y,-z); } 27 | P operator-(P b) { return *this+-b; } 28 | double operator*(P b){ return x*b.x + y*b.y + z*b.z; } 29 | P operator*(double k){ return P(x*k, y*k, z*k); } 30 | P operator%(P b){ return P(y*b.z - z*b.y, z*b.x - x*b.z, x*b.y - y*b.x); } // cross product 31 | P operator/(P b){ return b*(*this*b/(b*b)); } // projection of this onto b 32 | double operator!() { return sqrt(*this**this); } // length 33 | } p[4], q[4]; 34 | 35 | // Distance from point c to segment [a, b] 36 | double distSP(P a, P b, P c) { 37 | P pp = a + (c-a)/(b-a); 38 | if( !comp(!(a-pp) + !(pp-b), !(a-b)) ) return !( c-pp ); 39 | return min(!(a-c), !(b-c)); 40 | } 41 | 42 | // Distance from segment [a, b] to segment [c, d] 43 | double distSS(P a, P b, P c, P d) { 44 | P ba = b-a; 45 | P cd = c-d; 46 | P ca = c-a; 47 | P w = ba%cd; 48 | double dd = w*w; 49 | if( !comp(dd,0) ) { // both segments are parallel 50 | return min(min(distSP(a,b,c), distSP(a,b,d)), min(distSP(c,d,a), distSP(c,d,b))); 51 | } 52 | double x = ((ca%cd)*w)/dd; 53 | double y = ((ba%ca)*w)/dd; 54 | double z = ((ba%cd)*ca)/dd; 55 | if( x >= 0 && x <= 1 && y >= 0 && y <= 1 ) return !(w*z); 56 | return min(min(distSP(a,b,c), distSP(a,b,d)), min(distSP(c,d,a), distSP(c,d,b))); 57 | } 58 | 59 | // Distance from point d to triangle [a, b, c] 60 | double distPP(P a, P b, P c, P d) { 61 | P ba = b-a; 62 | P ca = c-a; 63 | P da = d-a; 64 | P w = ba%ca; 65 | P q = d-da/w; 66 | double x = (b-a)%(q-a) * w, y = (c-b)%(q-b) * w, z = (a-c)%(q-c) * w; 67 | if( x <= 0 && y <= 0 && z <= 0 || x >= 0 && y >= 0 && z >= 0 ) return !(da/w); 68 | return min( min(distSP(a,b,d), distSP(b,c,d)), distSP(c,a,d)); 69 | } 70 | 71 | int read() { 72 | fr(i,0,4) scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].z); 73 | fr(i,0,4) scanf("%lf%lf%lf", &q[i].x, &q[i].y, &q[i].z); 74 | 75 | double dist = 1./0. ; 76 | fr(i,0,4) fr(j,i+1,4) fr(k,j+1,4) fr(l,0,4) { 77 | double d = distPP(p[i], p[j], p[k], q[l]); 78 | if( d < dist ) dist = d; 79 | d = distPP(q[i], q[j], q[k], p[l]); 80 | if( d < dist ) dist = d; 81 | } 82 | fr(i,0,4) fr(j,i+1,4) fr(k,0,4) fr(l,k+1,4) { 83 | double d = distSS(p[i], p[j], q[k], q[l]); 84 | if( d < dist ) dist = d; 85 | } 86 | 87 | printf("%.2lf\n", dist); 88 | 89 | return 1; 90 | } 91 | 92 | void process() { 93 | 94 | } 95 | 96 | int main() { 97 | int t = 1; 98 | scanf("%d", &t); 99 | while( t-- && read() ) process(); 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /other/codigos_sueltos/star_war_filipe_martins.cpp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/codigos_sueltos/star_war_filipe_martins.cpp.pdf -------------------------------------------------------------------------------- /other/notebook_fidel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/notebook_fidel.pdf -------------------------------------------------------------------------------- /other/notebook_gaizka.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/notebook_gaizka.pdf -------------------------------------------------------------------------------- /other/notebook_uba.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/notebook_uba.pdf -------------------------------------------------------------------------------- /other/notebook_uniandes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/notebook_uniandes.pdf -------------------------------------------------------------------------------- /other/notebook_walter.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/other/notebook_walter.pdf -------------------------------------------------------------------------------- /pics/ancestors.mp: -------------------------------------------------------------------------------- 1 | input boxes 2 | 3 | vardef cuta(suffix a,b) expr p = 4 | draw p cutbefore bpath.a cutafter bpath.b; 5 | point .5*length p of p 6 | enddef; 7 | 8 | beginfig(1); 9 | verbatimtex \def\stk#1#2{$\displaystyle{\matrix{#1\cr#2\cr}}$} etex 10 | circleit.aa(btex\stk A{6} etex); 11 | circleit.bb(btex \stk B{3} etex); 12 | circleit.cc(btex \stk C{4} etex); 13 | circleit.dd(btex \stk D{-1} etex); 14 | circleit.ee(btex \stk E{1} etex); 15 | circleit.ff(btex \stk F{-5} etex); 16 | circleit.gg(btex \stk G{1} etex); 17 | 18 | u := 3cm; 19 | aa.c - bb.c = (0.75u, 0.75u); 20 | bb.c - cc.c = (0.5u, 0.75u); 21 | bb.c - dd.c = (-0.5u, 0.75u); 22 | 23 | aa.c - ee.c = (0.0u, 0.75u); 24 | 25 | aa.c - ff.c = (-0.75u, 0.75u); 26 | 27 | ff.c - gg.c = (0.2u, 0.75u); 28 | 29 | drawboxed(aa,bb,cc,dd,ee,ff,gg); 30 | 31 | label.ulft(btex$ $etex, cuta(aa,bb) aa.c{dir200}..bb.c); 32 | label.ulft(btex$ $etex, cuta(aa,ee) aa.c{dir-90}..ee.c); 33 | label.ulft(btex$ $etex, cuta(aa,ff) aa.c{dir-20}..ff.c); 34 | 35 | label.ulft(btex$ $etex, cuta(bb,cc) bb.c{dir210}..cc.c); 36 | label.ulft(btex$ $etex, cuta(bb,dd) bb.c{dir-20}..dd.c); 37 | 38 | label.ulft(btex$ $etex, cuta(ff,gg) ff.c{dir-90}..gg.c); 39 | 40 | endfig; 41 | 42 | end. -------------------------------------------------------------------------------- /pics/ascii-1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 16 | 22 | 27 | 28 | 29 | 31 | 32 | 34 | image/svg+xml 35 | 37 | 38 | 39 | 40 | 41 | 43 | ^..^ (OO) / \ ()() 65 | 66 | 67 | -------------------------------------------------------------------------------- /pics/barycenter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/pics/barycenter.png -------------------------------------------------------------------------------- /pics/circumcenter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/pics/circumcenter.png -------------------------------------------------------------------------------- /pics/cone.tikz: -------------------------------------------------------------------------------- 1 | \begin{tikzpicture} 2 | \begin{axis}[ 3 | domain=0:5, 4 | y domain=0:2*pi, 5 | xmin=-10, 6 | xmax=10, 7 | ymin=-10, 8 | ymax=10, 9 | samples=20] 10 | \addplot3 [mesh,draw=black,z buffer=sort,samples=20] 11 | ({x*cos(deg(y))}, 12 | {x*sin(deg(y))}, 13 | {x}); 14 | \addplot3 [mesh,draw=black,z buffer=sort] 15 | ({x*cos(deg(y))}, 16 | {x*sin(deg(y))}, 17 | {-x}); 18 | \end{axis} 19 | \end{tikzpicture}. 20 | -------------------------------------------------------------------------------- /pics/flights.mp: -------------------------------------------------------------------------------- 1 | u := 1mm; 2 | v := 3mm; 3 | 4 | vardef sqr(expr x) = x * x enddef; 5 | 6 | vardef P(expr x) = (-0.025 sqr(x) + 1.5x - 12.5) enddef; 7 | vardef Q(expr x) = (-0.300 sqr(x) + 18x - 240) enddef; 8 | 9 | def flight(expr i, a, b, c) = 10 | draw (a*u, c*u)--(b*u, c*u) dashed evenly; 11 | draw (a*u, 0)--(a*u, c*u+v); 12 | draw (b*u, 0)--(b*u, c*u+v); 13 | label.top(decimal(i), (.5(a+b)*u, c*u)); 14 | enddef; 15 | 16 | beginfig(1) 17 | draw (-10u,0)--(110u,0); 18 | 19 | draw (10u,0) for x=11 upto 50 : --(x*u,P(x)*u) endfor withpen pencircle scaled 1.5pt; 20 | draw (20u,0) for x=21 upto 40 : --(x*u,Q(x)*u) endfor withpen pencircle scaled 1.5pt; 21 | 22 | for i=0 upto 10 : 23 | fill fullcircle scaled 3pt shifted (10i * u, 0); 24 | label.bot(decimal(10i), (10i * u, 0)); 25 | endfor; 26 | 27 | flight(1, 0, 11, 0.975); 28 | flight(2, 20, 25, 22.500); 29 | flight(3, 25, 35, 30.000); 30 | flight(4, 45, 100, 4.375); 31 | 32 | endfig; 33 | 34 | end. -------------------------------------------------------------------------------- /pics/huzita.1: -------------------------------------------------------------------------------- 1 | %!PS 2 | %%BoundingBox: -1 -1 140 141 3 | %%HiResBoundingBox: -0.25 -0.25 139.78447 140.26993 4 | %%Creator: MetaPost 1.004 5 | %%CreationDate: 2011.11.24:1216 6 | %%Pages: 1 7 | %*Font: cmmi10 9.96265 9.96265 6c:88 8 | %*Font: cmr7 6.97385 6.97385 31:c 9 | %%BeginProlog 10 | %%EndProlog 11 | %%Page: 1 1 12 | 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop 13 | [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit 14 | newpath 0 68.03174 moveto 15 | 136.06348 68.03174 lineto stroke 16 | 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth 17 | newpath 68.03174 0 moveto 18 | 68.03174 136.06348 lineto stroke 19 | 116.38623 89.53282 moveto 20 | (p) cmmi10 9.96265 fshow 21 | 121.39873 88.03842 moveto 22 | (1) cmr7 6.97385 fshow 23 | 0 3 dtransform truncate idtransform setlinewidth pop 24 | newpath 113.38623 90.70898 moveto 0 0 rlineto stroke 25 | 85.96808 118.32343 moveto 26 | (p) cmmi10 9.96265 fshow 27 | 90.98058 116.82903 moveto 28 | (2) cmr7 6.97385 fshow 29 | newpath 90.70898 113.38623 moveto 0 0 rlineto stroke 30 | 132.34247 72.52615 moveto 31 | (l) cmmi10 9.96265 fshow 32 | 135.31506 71.03175 moveto 33 | (2) cmr7 6.97385 fshow 34 | 71.03174 133.35143 moveto 35 | (l) cmmi10 9.96265 fshow 36 | 74.00433 131.85703 moveto 37 | (1) cmr7 6.97385 fshow 38 | 0 0.5 dtransform truncate idtransform setlinewidth pop 39 | [3 3 ] 0 setdash 40 | newpath 22.67725 136.06348 moveto 41 | 136.06348 22.67725 lineto stroke 42 | [] 0 setdash 43 | newpath 113.38623 90.70898 moveto 44 | 68.03174 45.35449 lineto stroke 45 | newpath 69.56244 49.05002 moveto 46 | 68.03174 45.35449 lineto 47 | 71.72726 46.8852 lineto 48 | closepath 49 | gsave fill grestore stroke 50 | newpath 90.70898 113.38623 moveto 51 | 45.35449 68.03174 lineto stroke 52 | newpath 46.8852 71.72726 moveto 53 | 45.35449 68.03174 lineto 54 | 49.05002 69.56244 lineto 55 | closepath 56 | gsave fill grestore stroke 57 | showpage 58 | %%EOF 59 | -------------------------------------------------------------------------------- /pics/huzita.mp: -------------------------------------------------------------------------------- 1 | u := 0.8cm; 2 | 3 | beginfig(1) 4 | draw (0u, 3u)--(6u, 3u); 5 | draw (3u, 0u)--(3u, 6u); 6 | dotlabel.rt (btex $p_1$ etex, (5u, 4u)); 7 | dotlabel.top (btex $p_2$ etex, (4u, 5u)); 8 | label.top (btex $l_2$ etex, (6u, 3u)); 9 | label.rt (btex $l_1$ etex, (3u, 6u)); 10 | draw (1u, 6u)--(6u, 1u) dashed evenly; 11 | drawarrow (5u, 4u)--(3u, 2u); 12 | drawarrow (4u, 5u)--(2u, 3u); 13 | endfig; 14 | 15 | end. 16 | -------------------------------------------------------------------------------- /pics/incenter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/pics/incenter.png -------------------------------------------------------------------------------- /pics/journey.mp: -------------------------------------------------------------------------------- 1 | u := 1cm; 2 | 3 | beginfig(1) 4 | drawarrow (0, 0)--(1u, 0); 5 | drawarrow (1u, 0)--(2u, 0); 6 | drawarrow (2u, 0)--(2u, 1u); 7 | drawarrow (2u, 1u)--(1u, 1u); 8 | drawarrow (1u, 1u)--(1u, 0); 9 | 10 | drawarrow (1u, 0)--(2u, 0); 11 | drawarrow (2u, 0)--(3u, 0); 12 | drawarrow (3u, 0)--(3u, 1u); 13 | drawarrow (3u, 1u)--(2u, 1u); 14 | drawarrow (2u, 1u)--(2u, 0); 15 | 16 | drawarrow (2u, 0)--(3u, 0); 17 | drawarrow (3u, 0)--(4u, 0); 18 | drawarrow (4u, 0)--(4u, 1u); 19 | drawarrow (4u, 1u)--(3u, 1u); 20 | drawarrow (3u, 1u)--(3u, 0); 21 | 22 | fill fullcircle scaled 3pt; 23 | label.bot (btex $(0,0)$ etex, (0,0)); 24 | endfig; 25 | 26 | end. -------------------------------------------------------------------------------- /pics/kingdom.1: -------------------------------------------------------------------------------- 1 | %!PS 2 | %%BoundingBox: -8 -10 121 67 3 | %%HiResBoundingBox: -7.08133 -9.42036 120.46713 66.11327 4 | %%Creator: MetaPost 1.004 5 | %%CreationDate: 2011.11.24:1216 6 | %%Pages: 1 7 | %*Font: cmr10 9.96265 9.96265 31:f8 8 | %%BeginProlog 9 | %%EndProlog 10 | %%Page: 1 1 11 | 0 0 0 setrgbcolor 12 | newpath 1.4944 56.6929 moveto 13 | 1.4944 57.08926 1.33691 57.46933 1.05667 57.74957 curveto 14 | 0.77643 58.02982 0.39636 58.1873 0 58.1873 curveto 15 | -0.39636 58.1873 -0.77643 58.02982 -1.05667 57.74957 curveto 16 | -1.33691 57.46933 -1.4944 57.08926 -1.4944 56.6929 curveto 17 | -1.4944 56.29654 -1.33691 55.91647 -1.05667 55.63623 curveto 18 | -0.77643 55.35599 -0.39636 55.1985 0 55.1985 curveto 19 | 0.39636 55.1985 0.77643 55.35599 1.05667 55.63623 curveto 20 | 1.33691 55.91647 1.4944 56.29654 1.4944 56.6929 curveto closepath fill 21 | newpath 1.4944 0 moveto 22 | 1.4944 0.39636 1.33691 0.77643 1.05667 1.05667 curveto 23 | 0.77643 1.33691 0.39636 1.4944 0 1.4944 curveto 24 | -0.39636 1.4944 -0.77643 1.33691 -1.05667 1.05667 curveto 25 | -1.33691 0.77643 -1.4944 0.39636 -1.4944 0 curveto 26 | -1.4944 -0.39636 -1.33691 -0.77643 -1.05667 -1.05667 curveto 27 | -0.77643 -1.33691 -0.39636 -1.4944 0 -1.4944 curveto 28 | 0.39636 -1.4944 0.77643 -1.33691 1.05667 -1.05667 curveto 29 | 1.33691 -0.77643 1.4944 -0.39636 1.4944 0 curveto closepath fill 30 | newpath 58.1873 0 moveto 31 | 58.1873 0.39636 58.02982 0.77643 57.74957 1.05667 curveto 32 | 57.46933 1.33691 57.08926 1.4944 56.6929 1.4944 curveto 33 | 56.29654 1.4944 55.91647 1.33691 55.63623 1.05667 curveto 34 | 55.35599 0.77643 55.1985 0.39636 55.1985 0 curveto 35 | 55.1985 -0.39636 55.35599 -0.77643 55.63623 -1.05667 curveto 36 | 55.91647 -1.33691 56.29654 -1.4944 56.6929 -1.4944 curveto 37 | 57.08926 -1.4944 57.46933 -1.33691 57.74957 -1.05667 curveto 38 | 58.02982 -0.77643 58.1873 -0.39636 58.1873 0 curveto closepath fill 39 | newpath 58.1873 56.6929 moveto 40 | 58.1873 57.08926 58.02982 57.46933 57.74957 57.74957 curveto 41 | 57.46933 58.02982 57.08926 58.1873 56.6929 58.1873 curveto 42 | 56.29654 58.1873 55.91647 58.02982 55.63623 57.74957 curveto 43 | 55.35599 57.46933 55.1985 57.08926 55.1985 56.6929 curveto 44 | 55.1985 56.29654 55.35599 55.91647 55.63623 55.63623 curveto 45 | 55.91647 55.35599 56.29654 55.1985 56.6929 55.1985 curveto 46 | 57.08926 55.1985 57.46933 55.35599 57.74957 55.63623 curveto 47 | 58.02982 55.91647 58.1873 56.29654 58.1873 56.6929 curveto closepath fill 48 | newpath 114.8802 0 moveto 49 | 114.8802 0.39636 114.72272 0.77643 114.44247 1.05667 curveto 50 | 114.16223 1.33691 113.78217 1.4944 113.3858 1.4944 curveto 51 | 112.98944 1.4944 112.60938 1.33691 112.32913 1.05667 curveto 52 | 112.04889 0.77643 111.8914 0.39636 111.8914 0 curveto 53 | 111.8914 -0.39636 112.04889 -0.77643 112.32913 -1.05667 curveto 54 | 112.60938 -1.33691 112.98944 -1.4944 113.3858 -1.4944 curveto 55 | 113.78217 -1.4944 114.16223 -1.33691 114.44247 -1.05667 curveto 56 | 114.72272 -0.77643 114.8802 -0.39636 114.8802 0 curveto closepath fill 57 | -7.08133 58.7929 moveto 58 | (1) cmr10 9.96265 fshow 59 | -7.08133 -8.52036 moveto 60 | (2) cmr10 9.96265 fshow 61 | 54.20222 -9.42036 moveto 62 | (3) cmr10 9.96265 fshow 63 | 54.20222 59.6929 moveto 64 | (4) cmr10 9.96265 fshow 65 | 115.4858 -8.52036 moveto 66 | (5) cmr10 9.96265 fshow 67 | 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth [] 0 setdash 68 | 1 setlinecap 1 setlinejoin 10 setmiterlimit 69 | newpath 0 56.6929 moveto 70 | 0 0 lineto stroke 71 | 0 0.5 dtransform truncate idtransform setlinewidth pop 72 | newpath 0 0 moveto 73 | 56.6929 0 lineto stroke 74 | 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth 75 | newpath 56.6929 0 moveto 76 | 56.6929 56.6929 lineto stroke 77 | 0 0.5 dtransform truncate idtransform setlinewidth pop 78 | newpath 56.6929 0 moveto 79 | 113.3858 0 lineto stroke 80 | [3 3 ] 0 setdash 81 | newpath 0 56.6929 moveto 82 | 56.6929 56.6929 lineto stroke 83 | newpath 56.6929 56.6929 moveto 84 | 113.3858 0 lineto stroke 85 | showpage 86 | %%EOF 87 | -------------------------------------------------------------------------------- /pics/kingdom.mp: -------------------------------------------------------------------------------- 1 | u := 2cm; 2 | 3 | beginfig(1) 4 | z1 = (0u, 1u); 5 | z2 = (0u, 0u); 6 | z3 = (1u, 0u); 7 | z4 = (1u, 1u); 8 | z5 = (2u, 0u); 9 | 10 | for i=1 upto 5: 11 | fill fullcircle scaled 3pt shifted z[i]; 12 | endfor 13 | 14 | label.ulft("1", z1); 15 | label.llft("2", z2); 16 | label.bot ("3", z3); 17 | label.top ("4", z4); 18 | label.lrt ("5", z5); 19 | 20 | draw z1--z2; 21 | draw z2--z3; 22 | draw z3--z4; 23 | draw z3--z5; 24 | 25 | draw z1--z4 dashed evenly; 26 | draw z4--z5 dashed evenly; 27 | endfig; 28 | 29 | end. 30 | -------------------------------------------------------------------------------- /pics/lanes.mp: -------------------------------------------------------------------------------- 1 | 2 | w := 12cm; 3 | h := 8mm; 4 | e := .5pt; 5 | a := 5cm; 6 | b := 7cm; 7 | 8 | path c; 9 | 10 | c := (-3.5mm,-2mm){left}..{up}(-4mm,-1.5mm)-- 11 | (-4mm,1.5mm){up}..{right}(-3.5mm,2mm)-- 12 | (3.5mm,2mm){right}..{down}(4mm,1.5mm)-- 13 | (4mm,-1.5mm){down}..{left}(3.5mm,-2mm)--cycle; 14 | 15 | path d; 16 | 17 | q := 0.3mm; 18 | r := 1.2mm; 19 | 20 | d := (-3.5mm+r,-2mm+q){left}..{up}(-4mm+r,-1.5mm+q)-- 21 | (-4mm+r,1.5mm-q){up}..{right}(-3.5mm+r,2mm-q)-- 22 | (3.5mm-r,2mm-q){right}..{down}(4mm-r,1.5mm-q)-- 23 | (4mm-r,-1.5mm+q){down}..{left}(3.5mm-r,-2mm+q)--cycle; 24 | 25 | def car(expr p, k) = 26 | draw c shifted p; 27 | draw d shifted p shifted (-.7mm * k,0); 28 | enddef; 29 | 30 | beginfig(1) 31 | draw (0, 0)--(w, 0); 32 | draw (0, h)--(w, h) dashed evenly; 33 | draw (0,2h-e)--(w, 2h-e) dashed evenly; 34 | draw (0,2h+e)--(w, 2h+e) dashed evenly; 35 | draw (0,3h-e)--(w, 3h-e) dashed evenly; 36 | draw (0,3h+e)--(w, 3h+e) dashed evenly; 37 | draw (0,4h)--(w, 4h) dashed evenly; 38 | draw (0,5h)--(w, 5h); 39 | 40 | drawarrow (a, 0.5h)--(b, 0.5h); 41 | drawarrow (a, 1.5h)--(b, 1.5h); 42 | drawarrow (a, 2.5h)--(b, 2.5h); 43 | drawarrow (b, 2.5h)--(a, 2.5h); 44 | drawarrow (b, 3.5h)--(a, 3.5h); 45 | drawarrow (b, 4.5h)--(a, 4.5h); 46 | 47 | car((3cm,0.5h), 1); 48 | car((1cm,1.5h), 1); 49 | car((9cm,3.5h), -1); 50 | 51 | endfig; 52 | 53 | end; -------------------------------------------------------------------------------- /pics/law_of_sines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/pics/law_of_sines.png -------------------------------------------------------------------------------- /pics/makefile: -------------------------------------------------------------------------------- 1 | .PHONY: pics clean 2 | 3 | psfiles := $(patsubst %.mp,%.1,$(wildcard *.mp)) 4 | 5 | pics: $(psfiles) 6 | 7 | %.1: %.mp 8 | mpost $< 9 | 10 | clean: 11 | rm -f *.log *.mpx manual-figure*.dpth manual-figure*.pdf -------------------------------------------------------------------------------- /pics/manual-figure0.dpth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/pics/manual-figure0.dpth -------------------------------------------------------------------------------- /pics/manual-figure0.md5: -------------------------------------------------------------------------------- 1 | \def \tikzexternallastkey {FACD6F2671B4FD9EFE12349B41807A0C}% 2 | -------------------------------------------------------------------------------- /pics/manual-figure0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/pics/manual-figure0.pdf -------------------------------------------------------------------------------- /pics/orthocenter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhocki/notebook/5903dd4a774d829ce1df073ebd3be4cacee8e4ac/pics/orthocenter.png -------------------------------------------------------------------------------- /pics/r.bat: -------------------------------------------------------------------------------- 1 | pushd .. 2 | call r.bat 3 | popd 4 | -------------------------------------------------------------------------------- /pics/rectangle.1: -------------------------------------------------------------------------------- 1 | %!PS 2 | %%BoundingBox: -1 -10 111 130 3 | %%HiResBoundingBox: -0.25 -9.65906 110.80011 129.22513 4 | %%Creator: MetaPost 1.504 5 | %%CreationDate: 2012.04.16:2155 6 | %%Pages: 1 7 | %*Font: cmr10 9.96265 9.96265 31:ea 8 | %%BeginProlog 9 | %%EndProlog 10 | %%Page: 1 1 11 | 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop 12 | [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit 13 | newpath 0 0 moveto 14 | 110.55011 0 lineto stroke 15 | newpath 110.55011 0 moveto 16 | 0 0 lineto stroke 17 | newpath 0.36858 0 moveto 18 | 0.36858 36.85004 lineto 19 | 18.42502 36.85004 lineto 20 | 18.42502 0 lineto 21 | closepath stroke 22 | 0.3 0.3 0.3 setrgbcolor 23 | newpath 0.36858 0 moveto 24 | 0.36858 36.85004 lineto 25 | 18.42502 36.85004 lineto 26 | 18.42502 0 lineto 27 | closepath fill 28 | 0 0 0 setrgbcolor 29 | 6.72183 -9.65906 moveto 30 | (2) cmr10 9.96265 fshow 31 | newpath 18.7936 0 moveto 32 | 18.7936 55.27505 lineto 33 | 36.85004 55.27505 lineto 34 | 36.85004 0 lineto 35 | closepath stroke 36 | 1 1 1 setrgbcolor 37 | newpath 18.7936 0 moveto 38 | 18.7936 55.27505 lineto 39 | 36.85004 55.27505 lineto 40 | 36.85004 0 lineto 41 | closepath fill 42 | 0 0 0 setrgbcolor 43 | 25.14685 -9.65906 moveto 44 | (3) cmr10 9.96265 fshow 45 | newpath 37.21861 0 moveto 46 | 37.21861 18.42502 lineto 47 | 55.27505 18.42502 lineto 48 | 55.27505 0 lineto 49 | closepath stroke 50 | 0.7 0.7 0.7 setrgbcolor 51 | newpath 37.21861 0 moveto 52 | 37.21861 18.42502 lineto 53 | 55.27505 18.42502 lineto 54 | 55.27505 0 lineto 55 | closepath fill 56 | 0 0 0 setrgbcolor 57 | 43.57187 -9.65906 moveto 58 | (1) cmr10 9.96265 fshow 59 | newpath 55.64363 0 moveto 60 | 55.64363 128.97513 lineto 61 | 73.70007 128.97513 lineto 62 | 73.70007 0 lineto 63 | closepath stroke 64 | 1 1 1 setrgbcolor 65 | newpath 55.64363 0 moveto 66 | 55.64363 128.97513 lineto 67 | 73.70007 128.97513 lineto 68 | 73.70007 0 lineto 69 | closepath fill 70 | 0 0 0 setrgbcolor 71 | 61.99689 -9.65906 moveto 72 | (7) cmr10 9.96265 fshow 73 | newpath 74.06865 0 moveto 74 | 74.06865 55.27505 lineto 75 | 92.12509 55.27505 lineto 76 | 92.12509 0 lineto 77 | closepath stroke 78 | 0.7 0.7 0.7 setrgbcolor 79 | newpath 74.06865 0 moveto 80 | 74.06865 55.27505 lineto 81 | 92.12509 55.27505 lineto 82 | 92.12509 0 lineto 83 | closepath fill 84 | 0 0 0 setrgbcolor 85 | 80.4219 -9.65906 moveto 86 | (3) cmr10 9.96265 fshow 87 | newpath 92.49367 0 moveto 88 | 92.49367 92.12509 lineto 89 | 110.55011 92.12509 lineto 90 | 110.55011 0 lineto 91 | closepath stroke 92 | 0.3 0.3 0.3 setrgbcolor 93 | newpath 92.49367 0 moveto 94 | 92.49367 92.12509 lineto 95 | 110.55011 92.12509 lineto 96 | 110.55011 0 lineto 97 | closepath fill 98 | 0 0 0 setrgbcolor 99 | 98.84692 -9.65906 moveto 100 | (5) cmr10 9.96265 fshow 101 | showpage 102 | %%EOF 103 | -------------------------------------------------------------------------------- /pics/rectangle.8: -------------------------------------------------------------------------------- 1 | %!PS 2 | %%BoundingBox: -1 -10 56 38 3 | %%HiResBoundingBox: -0.46066 -9.65906 55.73572 37.3107 4 | %%Creator: MetaPost 1.504 5 | %%CreationDate: 2012.04.16:2155 6 | %%Pages: 1 7 | %*Font: cmr10 9.96265 9.96265 31:ea 8 | %%BeginProlog 9 | %%EndProlog 10 | %%Page: 1 1 11 | 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop 12 | [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit 13 | newpath 0 0 moveto 14 | 55.27505 0 lineto stroke 15 | newpath 55.27505 0 moveto 16 | 0 0 lineto stroke 17 | newpath 0.36858 0 moveto 18 | 0.36858 36.85004 lineto 19 | 18.42502 36.85004 lineto 20 | 18.42502 0 lineto 21 | closepath stroke 22 | 1 1 1 setrgbcolor 23 | newpath 0.36858 0 moveto 24 | 0.36858 36.85004 lineto 25 | 18.42502 36.85004 lineto 26 | 18.42502 0 lineto 27 | closepath fill 28 | 0 0 0 setrgbcolor 29 | 6.72183 -9.65906 moveto 30 | (2) cmr10 9.96265 fshow 31 | newpath 18.7936 0 moveto 32 | 18.7936 36.85004 lineto 33 | 36.85004 36.85004 lineto 34 | 36.85004 0 lineto 35 | closepath stroke 36 | 1 1 1 setrgbcolor 37 | newpath 18.7936 0 moveto 38 | 18.7936 36.85004 lineto 39 | 36.85004 36.85004 lineto 40 | 36.85004 0 lineto 41 | closepath fill 42 | 0 0 0 setrgbcolor 43 | 25.14685 -9.65906 moveto 44 | (2) cmr10 9.96265 fshow 45 | newpath 37.21861 0 moveto 46 | 37.21861 36.85004 lineto 47 | 55.27505 36.85004 lineto 48 | 55.27505 0 lineto 49 | closepath stroke 50 | 1 1 1 setrgbcolor 51 | newpath 37.21861 0 moveto 52 | 37.21861 36.85004 lineto 53 | 55.27505 36.85004 lineto 54 | 55.27505 0 lineto 55 | closepath fill 56 | 0 0 0 setrgbcolor 57 | 43.57187 -9.65906 moveto 58 | (2) cmr10 9.96265 fshow 59 | gsave newpath 0 0 moveto 60 | 55.27505 0 lineto 61 | 55.27505 36.85004 lineto 62 | 0 36.85004 lineto 63 | closepath clip 64 | 0 0.92131 dtransform truncate idtransform setlinewidth pop 65 | newpath -150 -50 moveto 66 | 50 150 lineto stroke 67 | newpath -142 -50 moveto 68 | 58 150 lineto stroke 69 | newpath -134 -50 moveto 70 | 66 150 lineto stroke 71 | newpath -126 -50 moveto 72 | 74 150 lineto stroke 73 | newpath -118 -50 moveto 74 | 82 150 lineto stroke 75 | newpath -110 -50 moveto 76 | 90 150 lineto stroke 77 | newpath -102 -50 moveto 78 | 98 150 lineto stroke 79 | newpath -94 -50 moveto 80 | 106 150 lineto stroke 81 | newpath -86 -50 moveto 82 | 114 150 lineto stroke 83 | newpath -78 -50 moveto 84 | 122 150 lineto stroke 85 | newpath -70 -50 moveto 86 | 130 150 lineto stroke 87 | newpath -62 -50 moveto 88 | 138 150 lineto stroke 89 | newpath -54 -50 moveto 90 | 146 150 lineto stroke 91 | newpath -46 -50 moveto 92 | 154 150 lineto stroke 93 | newpath -38 -50 moveto 94 | 162 150 lineto stroke 95 | newpath -30 -50 moveto 96 | 170 150 lineto stroke 97 | newpath -22 -50 moveto 98 | 178 150 lineto stroke 99 | newpath -14 -50 moveto 100 | 186 150 lineto stroke 101 | newpath -6 -50 moveto 102 | 194 150 lineto stroke 103 | newpath 2 -50 moveto 104 | 202 150 lineto stroke 105 | newpath 10 -50 moveto 106 | 210 150 lineto stroke 107 | newpath 18 -50 moveto 108 | 218 150 lineto stroke 109 | newpath 26 -50 moveto 110 | 226 150 lineto stroke 111 | newpath 34 -50 moveto 112 | 234 150 lineto stroke 113 | newpath 42 -50 moveto 114 | 242 150 lineto stroke 115 | newpath 50 -50 moveto 116 | 250 150 lineto stroke 117 | newpath 58 -50 moveto 118 | 258 150 lineto stroke 119 | newpath 66 -50 moveto 120 | 266 150 lineto stroke 121 | newpath 74 -50 moveto 122 | 274 150 lineto stroke 123 | newpath 82 -50 moveto 124 | 282 150 lineto stroke 125 | newpath 90 -50 moveto 126 | 290 150 lineto stroke 127 | newpath 98 -50 moveto 128 | 298 150 lineto stroke 129 | newpath 106 -50 moveto 130 | 306 150 lineto stroke 131 | newpath 114 -50 moveto 132 | 314 150 lineto stroke 133 | newpath 122 -50 moveto 134 | 322 150 lineto stroke 135 | newpath 130 -50 moveto 136 | 330 150 lineto stroke 137 | newpath 138 -50 moveto 138 | 338 150 lineto stroke 139 | newpath 146 -50 moveto 140 | 346 150 lineto stroke 141 | grestore 142 | 0 0.92131 dtransform truncate idtransform setlinewidth pop 143 | newpath 0 0 moveto 144 | 55.27505 0 lineto 145 | 55.27505 36.85004 lineto 146 | 0 36.85004 lineto 147 | closepath stroke 148 | showpage 149 | %%EOF 150 | -------------------------------------------------------------------------------- /pics/reflected_point.1: -------------------------------------------------------------------------------- 1 | %!PS 2 | %%BoundingBox: -46 -23 69 59 3 | %%HiResBoundingBox: -45.60449 -22.92725 68.28174 58.21657 4 | %%Creator: MetaPost 1.504 5 | %%CreationDate: 2012.04.16:2344 6 | %%Pages: 1 7 | %*Font: cmmi10 9.96265 9.96265 61:c00184 8 | %%BeginProlog 9 | %%EndProlog 10 | %%Page: 1 1 11 | 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop 12 | [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit 13 | newpath -45.35449 45.35449 moveto 14 | 68.03174 -22.67725 lineto stroke 15 | newpath 64.07626 -22.08871 moveto 16 | 68.03174 -22.67725 lineto 17 | 65.651 -19.46411 lineto 18 | closepath 19 | gsave fill grestore stroke 20 | newpath -41.39902 44.76596 moveto 21 | -45.35449 45.35449 lineto 22 | -42.97375 42.14136 lineto 23 | closepath 24 | gsave fill grestore stroke 25 | -29.78973 -13.19273 moveto 26 | (p) cmmi10 9.96265 fshow 27 | 0 3 dtransform truncate idtransform setlinewidth pop 28 | newpath -22.67725 -6.80324 moveto 0 0 rlineto stroke 29 | 13.43861 53.92706 moveto 30 | (q) cmmi10 9.96265 fshow 31 | newpath 11.33862 49.88988 moveto 0 0 rlineto stroke 32 | -41.38127 32.1614 moveto 33 | (a) cmmi10 9.96265 fshow 34 | newpath -34.01518 38.5509 moveto 0 0 rlineto stroke 35 | 58.79242 -13.77367 moveto 36 | (b) cmmi10 9.96265 fshow 37 | newpath 56.69243 -15.87366 moveto 0 0 rlineto stroke 38 | newpath -5.66931 21.54332 moveto 0 0 rlineto stroke 39 | -0.40144 20.53249 moveto 40 | (v) cmmi10 9.96265 fshow 41 | 0 0.5 dtransform truncate idtransform setlinewidth pop 42 | [3 3 ] 0 setdash 43 | newpath -22.67725 -6.80324 moveto 44 | 11.33862 49.88988 lineto stroke 45 | showpage 46 | %%EOF 47 | -------------------------------------------------------------------------------- /pics/reflected_point.2: -------------------------------------------------------------------------------- 1 | %!PS 2 | %%BoundingBox: -46 -23 69 59 3 | %%HiResBoundingBox: -45.60449 -22.92725 68.28174 58.21657 4 | %%Creator: MetaPost 1.504 5 | %%CreationDate: 2012.04.16:2344 6 | %%Pages: 1 7 | %*Font: cmmi10 9.96265 9.96265 61:c00184 8 | %%BeginProlog 9 | %%EndProlog 10 | %%Page: 1 1 11 | 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop 12 | [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit 13 | newpath -45.35449 45.35449 moveto 14 | 68.03174 -22.67725 lineto stroke 15 | newpath 64.07626 -22.08871 moveto 16 | 68.03174 -22.67725 lineto 17 | 65.651 -19.46411 lineto 18 | closepath 19 | gsave fill grestore stroke 20 | newpath -41.39902 44.76596 moveto 21 | -45.35449 45.35449 lineto 22 | -42.97375 42.14136 lineto 23 | closepath 24 | gsave fill grestore stroke 25 | -7.11249 -10.92488 moveto 26 | (p) cmmi10 9.96265 fshow 27 | 0 3 dtransform truncate idtransform setlinewidth pop 28 | newpath 0 -4.53539 moveto 0 0 rlineto stroke 29 | 13.43861 53.92706 moveto 30 | (q) cmmi10 9.96265 fshow 31 | newpath 11.33862 49.88988 moveto 0 0 rlineto stroke 32 | -41.38127 32.1614 moveto 33 | (a) cmmi10 9.96265 fshow 34 | newpath -34.01518 38.5509 moveto 0 0 rlineto stroke 35 | 58.79242 -13.77367 moveto 36 | (b) cmmi10 9.96265 fshow 37 | newpath 56.69243 -15.87366 moveto 0 0 rlineto stroke 38 | newpath -5.66931 21.54332 moveto 0 0 rlineto stroke 39 | -0.40144 20.53249 moveto 40 | (v) cmmi10 9.96265 fshow 41 | 0 0.5 dtransform truncate idtransform setlinewidth pop 42 | [3 3 ] 0 setdash 43 | newpath 0 -4.53539 moveto 44 | 11.33862 49.88988 lineto stroke 45 | showpage 46 | %%EOF 47 | -------------------------------------------------------------------------------- /pics/reflected_point.mp: -------------------------------------------------------------------------------- 1 | u := 0.8cm; 2 | 3 | beginfig(1) 4 | pair a, b; 5 | a := (-2u,2u); 6 | b := (3u,-1u); 7 | drawdblarrow a .. b; 8 | 9 | pair here; here := (-1u, -0.3u); 10 | pair there; there := (0.5u, 2.2u); 11 | 12 | pair hit; hit := (-0.25u, 0.95u); 13 | 14 | dotlabel.llft(btex $p$ etex, here); 15 | dotlabel.urt(btex $q$ etex, there); 16 | 17 | dotlabel.llft(btex $a$ etex, a - 0.1 * (a - b)); 18 | dotlabel.urt(btex $b$ etex, b - 0.1 * (b - a)); 19 | 20 | 21 | draw hit withpen pencircle scaled 3bp; 22 | 23 | label.rt(btex $v$ etex, hit + (0.1u, 0.05u)); 24 | 25 | draw here--there dashed evenly; 26 | 27 | endfig; 28 | 29 | end. -------------------------------------------------------------------------------- /pics/reflected_ray.1: -------------------------------------------------------------------------------- 1 | %!PS 2 | %%BoundingBox: -43 -1 43 67 3 | %%HiResBoundingBox: -42.76968 -0.25 42.76968 66.81061 4 | %%Creator: MetaPost 1.504 5 | %%CreationDate: 2012.04.16:2257 6 | %%Pages: 1 7 | %*Font: cmmi10 9.96265 9.96265 61:c0040004 8 | %%BeginProlog 9 | %%EndProlog 10 | %%Page: 1 1 11 | 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop 12 | [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit 13 | newpath -28.34645 0 moveto 14 | -28.34645 15.6553 -15.6553 28.34645 0 28.34645 curveto 15 | 15.6553 28.34645 28.34645 15.6553 28.34645 0 curveto stroke 16 | 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth 17 | newpath 0 28.34645 moveto 18 | 0 56.6929 lineto stroke 19 | 0 0.5 dtransform truncate idtransform setlinewidth pop 20 | newpath 1.53079 52.99733 moveto 21 | 0 56.6929 lineto 22 | -1.53079 52.99733 lineto 23 | closepath 24 | gsave fill grestore stroke 25 | newpath -42.51968 39.68486 moveto 26 | 0 28.34645 lineto stroke 27 | newpath -3.96509 27.81953 moveto 28 | 0 28.34645 lineto 29 | -3.17627 30.77766 lineto 30 | closepath 31 | gsave fill grestore stroke 32 | newpath 0 28.34645 moveto 33 | 42.51968 39.68486 lineto stroke 34 | newpath 39.34341 37.25365 moveto 35 | 42.51968 39.68486 lineto 36 | 38.5546 40.21178 lineto 37 | closepath 38 | gsave fill grestore stroke 39 | -3.25687 59.6929 moveto 40 | (~) cmmi10 9.96265 fshow 41 | -2.98996 59.6929 moveto 42 | (n) cmmi10 9.96265 fshow 43 | -24.5167 37.01566 moveto 44 | (~) cmmi10 9.96265 fshow 45 | -23.8929 37.01566 moveto 46 | (a) cmmi10 9.96265 fshow 47 | 18.00294 39.64465 moveto 48 | (~) cmmi10 9.96265 fshow 49 | 19.12204 37.01566 moveto 50 | (b) cmmi10 9.96265 fshow 51 | showpage 52 | %%EOF 53 | -------------------------------------------------------------------------------- /pics/reflected_ray.mp: -------------------------------------------------------------------------------- 1 | u := 1cm; 2 | 3 | beginfig(1) 4 | draw (-1u,0) .. (0u,1u) .. (1u,0); 5 | 6 | pair normal, incidence; 7 | normal := (0u, 2u); 8 | incidence := (0u, 1u); 9 | drawarrow incidence--normal; 10 | 11 | pair left, right; 12 | 13 | left := (-1.5u, 1.4u); 14 | right := (+1.5u, 1.4u); 15 | 16 | drawarrow left--incidence; 17 | drawarrow incidence--right; 18 | 19 | label.top(btex $\vec n$ etex, normal); 20 | label.top(btex $\vec a$ etex, 1/2[left,incidence]); 21 | label.top(btex $\vec b$ etex, 1/2[incidence, right]); 22 | endfig; 23 | 24 | end. -------------------------------------------------------------------------------- /src/c++/cout_con_precision.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | cout << fixed << setprecision(3) << 1.1225 << endl; -------------------------------------------------------------------------------- /src/c++/fgetws.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | int main(){ 10 | assert(setlocale(LC_ALL, "en_US.UTF-8") != NULL); 11 | wchar_t in_buf[512], out_buf[512]; 12 | swprintf(out_buf, 512, 13 | L"¿Podrías escribir un número?, Por ejemplo %d. " 14 | "¡Gracias, pingüino español!\n", 3); 15 | fputws(out_buf, stdout); 16 | fgetws(in_buf, 512, stdin); 17 | int n; 18 | swscanf(in_buf, L"%d", &n); 19 | swprintf(out_buf, 512, 20 | L"Escribiste %d, yo escribo ¿ÔÏàÚÑ~\n", n); 21 | fputws(out_buf, stdout); 22 | return 0; 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/c++/io_file.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int _main(){ 7 | freopen("entrada.in", "r", stdin); 8 | freopen("entrada.out", "w", stdout); 9 | 10 | string s; 11 | while (cin >> s){ 12 | cout << "Leí " << s << endl; 13 | } 14 | return 0; 15 | } 16 | 17 | 18 | int main(){ 19 | ifstream fin("entrada.in"); 20 | ofstream fout("entrada.out"); 21 | 22 | string s; 23 | while (fin >> s){ 24 | fout << "Leí " << s << endl; 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /src/c++/unicode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | int main(){ 12 | assert(setlocale(LC_ALL, "en_US.UTF-8") != NULL); 13 | wchar_t c; 14 | 15 | wstring s; 16 | while (getline(wcin, s)){ 17 | wcout << L"Leí : " << s << endl; 18 | for (int i=0; ib)?(a):(b)) 2 | int dp[1001][1001]; 3 | 4 | int lcs(const string &s, const string &t){ 5 | int m = s.size(), n = t.size(); 6 | if (m == 0 || n == 0) return 0; 7 | for (int i=0; i<=m; ++i) 8 | dp[i][0] = 0; 9 | for (int j=1; j<=n; ++j) 10 | dp[0][j] = 0; 11 | for (int i=0; i S(n); 10 | vector M(n+1, INF); 11 | for (int i = 0; i < n; ++i) scanf("%ld", &S[i]); 12 | M[0] = 0; 13 | int m = 0; 14 | for (int i = 0; i < S.size(); ++i){ 15 | int d = upper_bound(M.begin(), M.begin()+n, S[i])-M.begin(); 16 | if (S[i] != M[d-1]){ 17 | M[d] = S[i]; 18 | m = max(m,d); 19 | parent[S[i]] = M[d-1]; 20 | } 21 | } 22 | printf("%d\n", max(1, m)); 23 | } 24 | return 0; 25 | } -------------------------------------------------------------------------------- /src/dp/particion_troncos.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | O(n^3) 3 | dp[i][j] = Mínimo costo de partir la cadena entre las 4 | particiones i e j, ambas incluídas. 5 | */ 6 | int dp[1005][1005]; 7 | int p[1005]; 8 | 9 | int cubic(){ 10 | int n, m; 11 | while (scanf("%d %d", &n, &m)==2){ 12 | p[0] = 0; 13 | for (int i=1; i<=m; ++i){ 14 | scanf("%d", &p[i]); 15 | } 16 | p[m+1] = n; 17 | m += 2; 18 | 19 | for (int i=0; i=0; --i){ 24 | for (int j=i+2; j v; 3 | int maxSize; 4 | 5 | public: 6 | FenwickTree(int _maxSize) : maxSize(_maxSize+1) { 7 | v = vector(maxSize, 0LL); 8 | } 9 | 10 | void add(int where, long long what){ 11 | for (where++; where <= maxSize; where += where & -where){ 12 | v[where] += what; 13 | } 14 | } 15 | 16 | long long query(int where){ 17 | long long sum = v[0]; 18 | for (where++; where > 0; where -= where & -where){ 19 | sum += v[where]; 20 | } 21 | return sum; 22 | } 23 | 24 | long long query(int from, int to){ 25 | return query(to) - query(from-1); 26 | } 27 | 28 | }; 29 | -------------------------------------------------------------------------------- /src/estructuras/rmq/rmq_with_segment_tree.cpp: -------------------------------------------------------------------------------- 1 | // Usage: 2 | // N - Set to size of the array. 3 | // height - Fill with the data you want to run RMQ on. 4 | // 5 | // You might want to redefine the "better" function if 6 | // you are using a different comparison operator (For 7 | // example, to solve Range Maximum Query) 8 | // 9 | // 10 | // SegmentTree::build(0, 0, N - 1); // Preprocess 11 | // SegmentTree::get(0, 0, N - 1, i, j); // Returns the index 12 | // // of the smallest value 13 | // // in range [i, j] 14 | // 15 | 16 | int height[MAXN]; 17 | int N; 18 | 19 | namespace SegmentTree { 20 | int tree[1 << 18]; 21 | 22 | int better(int a, int b) { 23 | assert(0 <= a and a < N and 0 <= b and b < N); 24 | return height[a] <= height[b] ? a : b; 25 | } 26 | 27 | int build(int u, int l, int r) { 28 | if (l == r) return tree[u] = l; 29 | int m = (l + r) / 2; 30 | int a = build(2*u+1, l, m); 31 | int b = build(2*u+2, m+1, r); 32 | return tree[u] = better(a, b); 33 | } 34 | 35 | // Returns the INDEX of the best element in range [p, q] 36 | int get(int u, int l, int r, int p, int q) { 37 | assert(l <= p and q <= r and p <= q); 38 | if (l == p and r == q) return tree[u]; 39 | int m = (l + r) / 2; 40 | if (q <= m) return get(2*u+1, l, m, p, q); 41 | if (m + 1 <= p) return get(2*u+2, m+1, r, p, q); 42 | int a = get(2*u+1, l, m, p, m); 43 | int b = get(2*u+2, m+1, r, m+1, q); 44 | return better(a, b); 45 | } 46 | 47 | // Update the tree by setting the element `what` at position 48 | // `at`. Height is modified accordingly. 49 | void set(int u, int l, int r, int at, int what) { 50 | assert(l <= at and at <= r); 51 | if (l == at and at == r) { // leaf 52 | height[at] = what; 53 | assert(tree[u] == at); 54 | } else { 55 | int m = (l + r) / 2; 56 | if (at <= m) set(2*u+1, l, m, at, what); 57 | if (m + 1 <= at) set(2*u+2, m+1, r, at, what); 58 | tree[u] = better(tree[2*u+1], tree[2*u+2]); 59 | } 60 | } 61 | }; 62 | 63 | -------------------------------------------------------------------------------- /src/estructuras/rmq/rmq_with_table.cpp: -------------------------------------------------------------------------------- 1 | // Usage: 2 | // N - Set to size of the array. 3 | // height - Fill with the data you want to run RMQ on. 4 | // 5 | // You might want to redefine the "better" function if 6 | // you are using a different comparison operator (For 7 | // example, to solve Range Maximum Query) 8 | // 9 | // 10 | // RMQ::build(); // Preprocess 11 | // RMQ::get(i, j); // Returns the index 12 | // // of the smallest value 13 | // // in range [i, j] 14 | // 15 | 16 | int height[MAXN]; 17 | int N; 18 | 19 | namespace RMQ { 20 | const int L = 18; // 1 + log2(MAXN) 21 | int p[MAXN][L]; 22 | 23 | int better(int a, int b) { 24 | assert(0 <= a and a < N and 0 <= b and b < N); 25 | return height[a] <= height[b] ? a : b; 26 | } 27 | 28 | void build() { 29 | for (int i = 0; i < N; ++i) { 30 | p[i][0] = i; 31 | } 32 | for (int j = 1; j < L; ++j) { 33 | for (int i = 0; i < N; ++i) { 34 | p[i][j] = p[i][j - 1]; 35 | int length = 1 << (j - 1); 36 | if (i + length < N) { 37 | p[i][j] = better(p[i][j - 1], 38 | p[i + length][j - 1]); 39 | } 40 | } 41 | } 42 | } 43 | // Returns the index of the best value in range [from, to] 44 | int get(int from, int to) { 45 | int length = to - from + 1; 46 | int j = 0; 47 | while ((1 << (j + 1)) < length) j++; 48 | assert(j < L); 49 | return better(p[from][j], p[to - (1 << j) + 1][j]); 50 | } 51 | }; -------------------------------------------------------------------------------- /src/estructuras/segment_tree.cpp: -------------------------------------------------------------------------------- 1 | class SegmentTree{ 2 | public: 3 | vector arr, tree; 4 | int n; 5 | 6 | SegmentTree(){} 7 | SegmentTree(const vector &arr) : arr(arr) { 8 | initialize(); 9 | } 10 | 11 | //must be called after assigning a new arr. 12 | void initialize(){ 13 | n = arr.size(); 14 | tree.resize(4*n + 1); 15 | initialize(0, 0, n-1); 16 | } 17 | 18 | int query(int query_left, int query_right) const{ 19 | return query(0, 0, n-1, query_left, query_right); 20 | } 21 | 22 | void update(int where, int what){ 23 | update(0, 0, n-1, where, what); 24 | } 25 | 26 | private: 27 | int initialize(int node, int node_left, int node_right); 28 | int query(int node, int node_left, int node_right, 29 | int query_left, int query_right) const; 30 | void update(int node, int node_left, int node_right, 31 | int where, int what); 32 | }; 33 | 34 | int SegmentTree::initialize(int node, 35 | int node_left, int node_right){ 36 | if (node_left == node_right){ 37 | tree[node] = node_left; 38 | return tree[node]; 39 | } 40 | int half = (node_left + node_right) / 2; 41 | int ans_left = initialize(2*node+1, node_left, half); 42 | int ans_right = initialize(2*node+2, half+1, node_right); 43 | 44 | if (arr[ans_left] <= arr[ans_right]){ 45 | tree[node] = ans_left; 46 | }else{ 47 | tree[node] = ans_right; 48 | } 49 | return tree[node]; 50 | } 51 | 52 | int SegmentTree::query(int node, int node_left, int node_right, 53 | int query_left, int query_right) const{ 54 | if (node_right < query_left || query_right < node_left) 55 | return -1; 56 | if (query_left <= node_left && node_right <= query_right) 57 | return tree[node]; 58 | 59 | int half = (node_left + node_right) / 2; 60 | int ans_left = query(2*node+1, node_left, half, 61 | query_left, query_right); 62 | int ans_right = query(2*node+2, half+1, node_right, 63 | query_left, query_right); 64 | 65 | if (ans_left == -1) return ans_right; 66 | if (ans_right == -1) return ans_left; 67 | 68 | return(arr[ans_left] <= arr[ans_right] ? ans_left : ans_right); 69 | } 70 | 71 | void SegmentTree::update(int node, int node_left, int node_right, 72 | int where, int what){ 73 | if (where < node_left || node_right < where) return; 74 | if (node_left == where && where == node_right){ 75 | arr[where] = what; 76 | tree[node] = where; 77 | return; 78 | } 79 | int half = (node_left + node_right) / 2; 80 | if (where <= half){ 81 | update(2*node+1, node_left, half, where, what); 82 | }else{ 83 | update(2*node+2, half+1, node_right, where, what); 84 | } 85 | if (arr[tree[2*node+1]] <= arr[tree[2*node+2]]){ 86 | tree[node] = tree[2*node+1]; 87 | }else{ 88 | tree[node] = tree[2*node+2]; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/estructuras/treap.cpp: -------------------------------------------------------------------------------- 1 | #define null NULL 2 | 3 | struct Node { 4 | int x, y, size; 5 | long long sum; 6 | Node *l, *r; 7 | Node(int k) : x(k), y(rand()), size(1), 8 | l(null), r(null), sum(0) { } 9 | }; 10 | 11 | Node* relax(Node* p) { 12 | if (p) { 13 | p->size = 1; 14 | p->sum = p->x; 15 | if (p->l) { 16 | p->size += p->l->size; 17 | p->sum += p->l->sum; 18 | } 19 | if (p->r) { 20 | p->size += p->r->size; 21 | p->sum += p->r->sum; 22 | } 23 | } 24 | return p; 25 | } 26 | 27 | // Puts all elements <= x in l and all elements > x in r. 28 | void split(Node* t, int x, Node* &l, Node* &r) { 29 | if (t == null) l = r = null; else { 30 | if (t->x <= x) { 31 | split(t->r, x, t->r, r); 32 | l = relax(t); 33 | } else { 34 | split(t->l, x, l, t->l); 35 | r = relax(t); 36 | } 37 | } 38 | } 39 | 40 | Node* merge(Node* l, Node *r) { 41 | if (l == null) return relax(r); 42 | if (r == null) return relax(l); 43 | if (l->y > r->y) { 44 | l->r = merge(l->r, r); 45 | return relax(l); 46 | } else { 47 | r->l = merge(l, r->l); 48 | return relax(r); 49 | } 50 | } 51 | 52 | Node* insert(Node* t, Node* m) { 53 | if (t == null || m->y > t->y) { 54 | split(t, m->x, m->l, m->r); 55 | return relax(m); 56 | } 57 | if (m->x < t->x) t->l = insert(t->l, m); 58 | else t->r = insert(t->r, m); 59 | return relax(t); 60 | } 61 | 62 | Node* erase(Node* t, int x) { 63 | if (t == null) return null; 64 | if (t->x == x) { 65 | Node *q = merge(t->l, t->r); 66 | delete t; 67 | return relax(q); 68 | } else { 69 | if (x < t->x) t->l = erase(t->l, x); 70 | else t->r = erase(t->r, x); 71 | return relax(t); 72 | } 73 | } 74 | 75 | // Returns any node with the given x. 76 | Node* find(Node* cur, int x) { 77 | while (cur != null and cur->x != x) { 78 | if (x < cur->x) cur = cur->l; 79 | else cur = cur->r; 80 | } 81 | return cur; 82 | } 83 | 84 | Node* find_kth(Node* cur, int k) { 85 | while (cur != null and k >= 0) { 86 | if (cur->l && cur->l->size > k) { 87 | cur = cur->l; 88 | continue; 89 | } 90 | if (cur->l) 91 | k -= cur->l->size; 92 | if (k == 0) return cur; 93 | k--; 94 | cur = cur->r; 95 | } 96 | return cur; 97 | } 98 | 99 | long long sum(Node* p, int x) { // find the sum of elements <= x 100 | if (p == null) return 0LL; 101 | if (p->x > x) return sum(p->l, x); 102 | long long ans = (p->l ? p->l->sum : 0) + p->x + sum(p->r, x); 103 | assert(ans >= 0); 104 | return ans; 105 | } 106 | -------------------------------------------------------------------------------- /src/geometria/check_segment_intersection.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Returns the cross product of the segment that goes from 3 | (x1, y1) to (x3, y3) with the segment that goes from 4 | (x1, y1) to (x2, y2) 5 | */ 6 | int direction(int x1, int y1, int x2, int y2, int x3, int y3) { 7 | return (x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1); 8 | } 9 | 10 | /* 11 | Finds the intersection between two segments (Not infinite 12 | lines!) 13 | Segment 1 goes from point (x0, y0) to (x1, y1). 14 | Segment 2 goes from point (x2, y2) to (x3, y3). 15 | 16 | (Can be modified to find the intersection between a segment 17 | and a line) 18 | 19 | Handles the case when the 2 segments are: 20 | *Parallel but don't lie on the same line (No intersection) 21 | *Parallel and both lie on the same line (Infinite 22 | *intersections or no intersections) 23 | *Not parallel (One intersection or no intersections) 24 | 25 | Returns true if the segments do intersect in any case. 26 | */ 27 | bool segment_segment_intersection(int x1, int y1, 28 | int x2, int y2, 29 | 30 | int x3, int y3, 31 | int x4, int y4){ 32 | 33 | int d1 = direction(x3, y3, x4, y4, x1, y1); 34 | int d2 = direction(x3, y3, x4, y4, x2, y2); 35 | int d3 = direction(x1, y1, x2, y2, x3, y3); 36 | int d4 = direction(x1, y1, x2, y2, x4, y4); 37 | bool b1 = d1 > 0 and d2 < 0 or d1 < 0 and d2 > 0; 38 | bool b2 = d3 > 0 and d4 < 0 or d3 < 0 and d4 > 0; 39 | if (b1 and b2) return true; 40 | /* point_in_box is on segment_segmet_intersection */ 41 | if (d1 == 0 and point_in_box(x1, y1, x3, y3, x4, y4)) 42 | return true; 43 | 44 | if (d2 == 0 and point_in_box(x2, y2, x3, y3, x4, y4)) 45 | return true; 46 | 47 | if (d3 == 0 and point_in_box(x3, y3, x1, y1, x2, y2)) 48 | return true; 49 | 50 | if (d4 == 0 and point_in_box(x4, y4, x1, y1, x2, y2)) 51 | return true; 52 | 53 | return false; 54 | } -------------------------------------------------------------------------------- /src/geometria/circle_through_3_points.cpp: -------------------------------------------------------------------------------- 1 | point center(const point &p, const point &q, const point &r) { 2 | double ax = q.x - p.x; 3 | double ay = q.y - p.y; 4 | double bx = r.x - p.x; 5 | double by = r.y - p.y; 6 | double d = ax*by - bx*ay; 7 | 8 | if (cmp(d, 0) == 0) { 9 | printf("Points are collinear!\n"); 10 | assert(false); 11 | } 12 | 13 | double cx = (q.x + p.x) / 2; 14 | double cy = (q.y + p.y) / 2; 15 | double dx = (r.x + p.x) / 2; 16 | double dy = (r.y + p.y) / 2; 17 | 18 | double t1 = bx*dx + by*dy; 19 | double t2 = ax*cx + ay*cy; 20 | 21 | double x = (by*t2 - ay*t1) / d; 22 | double y = (ax*t1 - bx*t2) / d; 23 | 24 | return point(x, y); 25 | } -------------------------------------------------------------------------------- /src/geometria/distance_point_to_line.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Returns the closest distance between point pnt and the line 3 | that passes through points a and b 4 | Idea by: 5 | http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ 6 | */ 7 | double distance_point_to_line(const point &a, const point &b, 8 | const point &pnt){ 9 | double u = 10 | ((pnt.x - a.x)*(b.x - a.x)+(pnt.y - a.y)*(b.y - a.y)) 11 | /distsqr(a, b); 12 | point intersection; 13 | intersection.x = a.x + u*(b.x - a.x); 14 | intersection.y = a.y + u*(b.y - a.y); 15 | return dist(pnt, intersection); 16 | } 17 | -------------------------------------------------------------------------------- /src/geometria/distance_point_to_segment.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Returns the closest distance between point pnt and the segment 3 | that goes from point a to b 4 | Idea by: 5 | http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ 6 | */ 7 | double distance_point_to_segment(const point &a,const point &b, 8 | const point &pnt){ 9 | double u = 10 | ((pnt.x - a.x)*(b.x - a.x) + (pnt.y - a.y)*(b.y - a.y)) 11 | /distsqr(a, b); 12 | point intersection; 13 | intersection.x = a.x + u*(b.x - a.x); 14 | intersection.y = a.y + u*(b.y - a.y); 15 | if (u < 0.0 || u > 1.0){ 16 | return min(dist(a, pnt), dist(b, pnt)); 17 | } 18 | return dist(pnt, intersection); 19 | } 20 | -------------------------------------------------------------------------------- /src/geometria/grahamscan.cpp: -------------------------------------------------------------------------------- 1 | //Graham scan: Complexity: O(n log n) 2 | struct point{ 3 | int x,y; 4 | point() {} 5 | point(int X, int Y) : x(X), y(Y) {} 6 | }; 7 | 8 | point pivot; 9 | 10 | inline int distsqr(const point &a, const point &b){ 11 | return (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y); 12 | } 13 | 14 | inline double dist(const point &a, const point &b){ 15 | return sqrt(distsqr(a, b)); 16 | } 17 | 18 | //retorna > 0 si c esta a la izquierda del segmento AB 19 | //retorna < 0 si c esta a la derecha del segmento AB 20 | //retorna == 0 si c es colineal con el segmento AB 21 | inline 22 | int cross(const point &a, const point &b, const point &c){ 23 | return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y); 24 | } 25 | 26 | //Self < that si esta a la derecha del segmento Pivot-That 27 | bool angleCmp(const point &self, const point &that){ 28 | int t = cross(pivot, that, self); 29 | if (t < 0) return true; 30 | if (t == 0){ 31 | //Self < that si está más cerquita 32 | return (distsqr(pivot, self) < distsqr(pivot, that)); 33 | } 34 | return false; 35 | } 36 | 37 | vector graham(vector p){ 38 | //Metemos el más abajo más a la izquierda en la posición 0 39 | for (int i=1; i chull(p.begin(), p.begin()+3); 52 | 53 | //Ahora sí!!! 54 | for (int i=3; i= 2 && 56 | cross(chull[chull.size()-2], 57 | chull[chull.size()-1], 58 | p[i]) <=0){ 59 | chull.erase(chull.end() - 1); 60 | } 61 | chull.push_back(p[i]); 62 | } 63 | //chull contiene los puntos del convex hull ordenados 64 | //anti-clockwise. No contiene ningún punto repetido. El 65 | //primer punto no es el mismo que el último, i.e, la última 66 | //arista va de chull[chull.size()-1] a chull[0] 67 | return chull; 68 | } 69 | -------------------------------------------------------------------------------- /src/geometria/great_circle_distance.cpp: -------------------------------------------------------------------------------- 1 | // Returns the shortest distance on the surface of a sphere with 2 | // radius R from point A to point B. 3 | // Both points are described as a pair of latitude and longitude 4 | // angles, in degrees. 5 | // 6 | // -90 (South Pole) <= latitude <= +90 (North Pole) 7 | // -180 (West of meridian) <= longitude <= +180 (East of meridian) 8 | // 9 | double greatCircle(double laa, double loa, 10 | double lab, double lob, 11 | double R = 6378.0){ 12 | const double PI = acos(-1.0); 13 | // Convert to radians 14 | laa *= PI / 180.0; loa *= PI / 180.0; 15 | lab *= PI / 180.0; lob *= PI / 180.0; 16 | 17 | double u[3] = { cos(laa) * sin(loa), cos(laa) * cos(loa), 18 | sin(laa) }; 19 | double v[3] = { cos(lab) * sin(lob), cos(lab) * cos(lob), 20 | sin(lab) }; 21 | double dot = u[0] * v[0] + u[1] * v[1] + u[2] * v[2]; 22 | bool flip = false; 23 | if (dot < 0.0){ 24 | flip = true; 25 | for (int i = 0; i < 3; i++) v[i] = -v[i]; 26 | } 27 | double cr[3] = { u[1] * v[2] - u[2] * v[1], 28 | u[2] * v[0] - u[0] * v[2], 29 | u[0] * v[1] - u[1] * v[0] }; 30 | double theta = asin(sqrt(cr[0] * cr[0] + 31 | cr[1] * cr[1] + 32 | cr[2] * cr[2])); 33 | double len = theta * R; 34 | if (flip) len = PI * R - len; 35 | return len; 36 | } -------------------------------------------------------------------------------- /src/geometria/highlight.sh: -------------------------------------------------------------------------------- 1 | source-highlight -i $1.cpp -o $1.tex -s cpp -f latexcolor 2 | 3 | -------------------------------------------------------------------------------- /src/geometria/is_convex_polygon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Returns positive if a-b-c makes a left turn. 3 | Returns negative if a-b-c makes a right turn. 4 | Returns 0.0 if a-b-c are colineal. 5 | */ 6 | double turn(const point &a, const point &b, const point &c){ 7 | double z = (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x); 8 | if (fabs(z) < 1e-9) return 0.0; 9 | return z; 10 | } 11 | 12 | /* 13 | Returns true if polygon p is convex. 14 | False if it's concave or it can't be determined 15 | (For example, if all points are colineal we can't 16 | make a choice). 17 | */ 18 | bool isConvexPolygon(const vector &p){ 19 | int mask = 0; 20 | int n = p.size(); 21 | for (int i=0; i 0.0){ 28 | mask |= 2; 29 | } 30 | if (mask == 3) return false; 31 | } 32 | return mask != 0; 33 | } 34 | -------------------------------------------------------------------------------- /src/geometria/is_inside_concave_polygon.cpp: -------------------------------------------------------------------------------- 1 | //Point 2 | //Choose one of these two: 3 | struct P { 4 | double x, y; P(){}; P(double q, double w) : x(q), y(w){} 5 | }; 6 | struct P { 7 | int x, y; P(){}; P(int q, int w) : x(q), y(w){} 8 | }; 9 | 10 | // Polar angle 11 | // Returns an angle in the range [0, 2*Pi) of a given 12 | // Cartesian point. If the point is (0,0), -1.0 is returned. 13 | 14 | // REQUIRES: 15 | // include math.h 16 | // define EPS 0.000000001, or your choice 17 | // P has members x and y. 18 | double polarAngle( P p ) 19 | { 20 | if(fabs(p.x) <= EPS && fabs(p.y) <= EPS) return -1.0; 21 | if(fabs(p.x) <= EPS) return (p.y > EPS ? 1.0 : 3.0) * acos(0); 22 | double theta = atan(1.0 * p.y / p.x); 23 | if(p.x > EPS) 24 | return (p.y >= -EPS ? theta : (4*acos(0) + theta)); 25 | else 26 | return(2 * acos( 0 ) + theta); 27 | } 28 | 29 | //Point inside polygon 30 | // Returns true iff p is inside poly. 31 | // PRE: The vertices of poly are ordered (either clockwise or 32 | // counter-clockwise. 33 | // POST: Modify code inside to handle the special case of "on 34 | // an edge". 35 | // REQUIRES: 36 | // polarAngle() 37 | // include math.h 38 | // include vector 39 | // define EPS 0.000000001, or your choice 40 | bool pointInPoly( P p, vector< P > &poly ) 41 | { 42 | int n = poly.size(); 43 | double ang = 0.0; 44 | for(int i = n - 1, j = 0; j < n; i = j++){ 45 | P v( poly[i].x - p.x, poly[i].y - p.y ); 46 | P w( poly[j].x - p.x, poly[j].y - p.y ); 47 | double va = polarAngle(v); 48 | double wa = polarAngle(w); 49 | double xx = wa - va; 50 | if(va < -0.5 || wa < -0.5 || fabs(fabs(xx)-2*acos(0)) < EPS){ 51 | // POINT IS ON THE EDGE 52 | assert( false ); 53 | ang += 2 * acos( 0 ); 54 | continue; 55 | } 56 | if( xx < -2 * acos( 0 ) ) ang += xx + 4 * acos( 0 ); 57 | else if( xx > 2 * acos( 0 ) ) ang += xx - 4 * acos( 0 ); 58 | else ang += xx; 59 | } 60 | return( ang * ang > 1.0 ); 61 | } 62 | -------------------------------------------------------------------------------- /src/geometria/is_inside_convex_polygon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Returns true if point a is inside convex polygon p. Note 3 | that if point a lies on the border of p it is considered 4 | outside. 5 | 6 | We assume p is convex! The result is useless if p is 7 | concave. 8 | */ 9 | bool insideConvexPolygon(const vector &p, 10 | const point &a){ 11 | int mask = 0; 12 | int n = p.size(); 13 | for (int i=0; i 0.0){ 19 | mask |= 2; 20 | }else if (z == 0.0) return false; 21 | if (mask == 3) return false; 22 | } 23 | return mask != 0; 24 | } 25 | -------------------------------------------------------------------------------- /src/geometria/line_line_intersection.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Finds the intersection between two lines (Not segments! 3 | Infinite lines) 4 | Line 1 passes through points (x0, y0) and (x1, y1). 5 | Line 2 passes through points (x2, y2) and (x3, y3). 6 | 7 | Handles the case when the 2 lines are the same (infinite 8 | intersections), 9 | parallel (no intersection) or only one intersection. 10 | */ 11 | void line_line_intersection(double x0, double y0, 12 | double x1, double y1, 13 | 14 | double x2, double y2, 15 | double x3, double y3){ 16 | #ifndef EPS 17 | #define EPS 1e-9 18 | #endif 19 | 20 | double t0 = (y3-y2)*(x0-x2)-(x3-x2)*(y0-y2); 21 | double t1 = (x1-x0)*(y2-y0)-(y1-y0)*(x2-x0); 22 | double det = (y1-y0)*(x3-x2)-(y3-y2)*(x1-x0); 23 | if (fabs(det) < EPS){ 24 | //parallel 25 | if (fabs(t0) < EPS || fabs(t1) < EPS){ 26 | //same line 27 | printf("LINE\n"); 28 | }else{ 29 | //just parallel 30 | printf("NONE\n"); 31 | } 32 | }else{ 33 | t0 /= det; 34 | t1 /= det; 35 | double x = x0 + t0*(x1-x0); 36 | double y = y0 + t0*(y1-y0); 37 | //intersection is point (x, y) 38 | printf("POINT %.2lf %.2lf\n", x, y); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/geometria/minimum_enclosing_circle.cpp: -------------------------------------------------------------------------------- 1 | // Complexity is O(n) (expected) 2 | 3 | const int MAXN = 100005; 4 | 5 | struct Point { 6 | double x,y; Point(){} Point(double x, double y) : x(x), y(y){} 7 | double length() const { return sqrtl(x*x + y*y); } 8 | }; 9 | 10 | Point operator + (const Point &a, const Point &b) { 11 | return Point(a.x + b.x, a.y + b.y); 12 | } 13 | Point operator - (const Point &a, const Point &b) { 14 | return Point(a.x - b.x, a.y - b.y); 15 | } 16 | Point operator / (const Point &a, double s) { 17 | return Point(a.x / s, a.y / s); 18 | } 19 | double operator ^ (const Point &a, const Point &b) { 20 | return a.x * b.y - a.y * b.x; 21 | } 22 | double operator * (const Point &a, const Point &b) { 23 | return a.x * b.x + a.y * b.y; 24 | } 25 | 26 | // Real algorithm starts below 27 | typedef pair Circle; 28 | 29 | bool in_circle(Circle c, Point p){ 30 | return cmp((p - c.first).length(), c.second) <= 0; 31 | } 32 | 33 | Point circumcenter(Point p, Point q, Point r) { 34 | Point a = p - r, b = q - r; 35 | Point c = Point(a * (p + r) / 2, b * (q + r) / 2); 36 | double x = c ^ Point(a.y, b.y); 37 | double y = Point(a.x, b.x) ^ c; 38 | double d = a ^ b; 39 | return Point(x, y) / d; 40 | } 41 | 42 | Point T[MAXN]; 43 | 44 | // Fill T with the points and call spanning_circle(n). 45 | Circle spanning_circle(int n) { 46 | random_shuffle(T, T + n); 47 | Circle ans(Point(0, 0), -INFINITY); 48 | for (int i = 0; i < n; i++) { 49 | if (!in_circle(ans, T[i])) { 50 | ans = Circle(T[i], 0); 51 | for (int j = 0; j < i; j++) { 52 | if (!in_circle(ans, T[j])) { 53 | ans = Circle( (T[i] + T[j]) / 2, 54 | (T[i] - T[j]).length() / 2); 55 | for (int k = 0; k < j; k++) { 56 | if (!in_circle(ans, T[k])) { 57 | Point o = circumcenter(T[i], T[j], 58 | T[k]); 59 | ans = Circle(o, (o - T[k]).length()); 60 | } 61 | } 62 | } 63 | } 64 | } 65 | } 66 | return ans; 67 | } 68 | -------------------------------------------------------------------------------- /src/geometria/monotonechain.cpp: -------------------------------------------------------------------------------- 1 | // Convex Hull: Andrew's Monotone Chain Convex Hull 2 | // Complexity: O(n log n) (But lower constant than Graham Scan) 3 | 4 | typedef long long CoordType; 5 | 6 | struct Point { 7 | CoordType x, y; 8 | bool operator <(const Point &p) const { 9 | return x < p.x || (x == p.x && y < p.y); 10 | } 11 | }; 12 | 13 | // 2D cross product. Returns a positive value, if OAB makes a 14 | // counter-clockwise turn, negative for clockwise turn, and zero 15 | // if the points are collinear. 16 | CoordType cross(const Point &O, const Point &A, const Point &B){ 17 | return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x); 18 | } 19 | 20 | // Returns a list of points on the convex hull in 21 | // counter-clockwise order. Note: the last point in the returned 22 | // list is the same as the first one. 23 | vector convexHull(vector P){ 24 | int n = P.size(), k = 0; 25 | vector H(2*n); 26 | // Sort points lexicographically 27 | sort(P.begin(), P.end()); 28 | // Build lower hull 29 | for (int i = 0; i < n; i++) { 30 | while (k >= 2 && cross(H[k-2], H[k-1], P[i]) <= 0) k--; 31 | H[k++] = P[i]; 32 | } 33 | // Build upper hull 34 | for (int i = n-2, t = k+1; i >= 0; i--) { 35 | while (k >= t && cross(H[k-2], H[k-1], P[i]) <= 0) k--; 36 | H[k++] = P[i]; 37 | } 38 | H.resize(k); 39 | return H; 40 | } 41 | -------------------------------------------------------------------------------- /src/geometria/parallelepiped_union_volume.cpp: -------------------------------------------------------------------------------- 1 | // Complexity: O(n^2 log n), where n is the number 2 | // of boxes. 3 | namespace BoxUnion { 4 | long long get_volume(const vector &r) { 5 | vector z; 6 | for (int i = 0; i < r.size(); ++i) { 7 | z.push_back(r[i].z1); 8 | z.push_back(r[i].z2); 9 | } 10 | sort(z.begin(), z.end()); 11 | z.resize(unique(z.begin(), z.end()) - z.begin()); 12 | 13 | long long ans = 0; 14 | for (int i = 1; i < z.size(); ++i) { 15 | vector boxes; 16 | for (int j = 0; j < r.size(); ++j) { 17 | if (r[j].z1 < z[i] and z[i] <= r[j].z2) { 18 | boxes.push_back(r[j]); 19 | } 20 | } 21 | ans += RectangleUnion::get_area(boxes)*(z[i]-z[i-1]); 22 | } 23 | return ans; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/geometria/polygon_area.cpp: -------------------------------------------------------------------------------- 1 | //P es un polígono ordenado anticlockwise. 2 | //Si es clockwise, retorna el area negativa. 3 | //Si no esta ordenado retorna pura mierda. 4 | //P[0] != P[n-1] 5 | double PolygonArea(const vector &p){ 6 | double r = 0.0; 7 | for (int i=0; i Polygon; 3 | 4 | // This is not standard intersection because it returns false 5 | // when the intersection point is exactly the t=1 endpoint of 6 | // the segment. This is OK for this algorithm but not for general 7 | // use. 8 | bool segment_line_intersection(Double x0, Double y0, 9 | Double x1, Double y1, Double x2, Double y2, 10 | Double x3, Double y3, Double &x, Double &y){ 11 | 12 | Double t0 = (y3-y2)*(x0-x2) - (x3-x2)*(y0-y2); 13 | Double t1 = (x1-x0)*(y2-y0) - (y1-y0)*(x2-x0); 14 | Double det =(y1-y0)*(x3-x2) - (y3-y2)*(x1-x0); 15 | 16 | if (fabs(det) < EPS){ 17 | //Paralelas 18 | return false; 19 | }else{ 20 | t0 /= det; 21 | t1 /= det; 22 | if (cmp(0, t0) <= 0 and cmp(t0, 1) < 0){ 23 | x = x0 + t0 * (x1-x0); 24 | y = y0 + t0 * (y1-y0); 25 | return true; 26 | } 27 | return false; 28 | } 29 | } 30 | 31 | // Returns the polygons that result of cutting the CONVEX 32 | // polygon p by the infinite line that passes through (x0, y0) 33 | // and (x1, y1). 34 | // The returned value has either 1 element if this line 35 | // doesn't cut the polygon at all (or barely touches it) 36 | // or 2 elements if the line does split the polygon. 37 | vector split(const Polygon &p, Double x0, Double y0, 38 | Double x1, Double y1) { 39 | int hits = 0, side = 0; 40 | Double x, y; 41 | vector ans(2); 42 | 43 | for (int i = 0; i < p.size(); ++i) { 44 | int j = (i + 1) % p.size(); 45 | if (segment_line_intersection(p[i].x, p[i].y, 46 | p[j].x, p[j].y, x0, y0, x1, y1, x, y)) { 47 | hits++; 48 | ans[side].push_back(p[i]); 49 | if (cmp(p[i].x, x) != 0 or cmp(p[i].y, y) != 0) { 50 | ans[side].push_back(Point(x, y)); 51 | } 52 | side ^= 1; 53 | ans[side].push_back(Point(x, y)); 54 | } else { 55 | ans[side].push_back(p[i]); 56 | } 57 | } 58 | return hits < 2 ? vector(1, p) : ans; 59 | } 60 | -------------------------------------------------------------------------------- /src/grafos/bellman.cpp: -------------------------------------------------------------------------------- 1 | //Complejidad: O(V*E) 2 | 3 | const int oo = 1000000000; 4 | struct edge{ 5 | int v, w; edge(){} edge(int v, int w) : v(v), w(w) {} 6 | }; 7 | vector g[MAXNODES]; 8 | 9 | int d[MAXNODES]; 10 | int p[MAXNODES]; 11 | // Retorna falso si hay un ciclo de costo negativo alcanzable 12 | // desde s. Si retorna verdadero, entonces d[i] contiene la 13 | // distancia más corta para ir de s a i. Si se quiere 14 | // determinar la existencia de un costo negativo que no 15 | // necesariamente sea alcanzable desde s, se crea un nuevo 16 | // nodo A y nuevo nodo B. Para todo nodo original u se crean 17 | // las aristas dirigidas (A, u) con peso 1 y (u, B) con peso 18 | // 1. Luego se corre el algoritmo de Bellman-Ford iniciando en 19 | // A. 20 | bool bellman(int s, int n){ 21 | for (int i=0; i seen(n, false); 50 | deque cycle; 51 | int cur = v; 52 | for (; !seen[cur]; cur = p[cur]){ 53 | seen[cur] = true; 54 | cycle.push_front(cur); 55 | } 56 | cycle.push_front(cur); 57 | //there's a negative cycle that goes from 58 | //cycle.front() until it reaches itself again 59 | printf("Negative weight cycle reachable from s:\n"); 60 | int i = 0; 61 | do{ 62 | printf("%d ", cycle[i]); 63 | i++; 64 | }while(cycle[i] != cycle[0]); 65 | printf("\n"); 66 | // Negative weight cycle found 67 | 68 | return false; 69 | } 70 | } 71 | } 72 | return true; 73 | } 74 | -------------------------------------------------------------------------------- /src/grafos/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | // //Complejidad: O(E log V) 2 | // ¡Si hay ciclos de peso negativo, el algoritmo se queda 3 | // en un ciclo infinito! 4 | // Usar Bellman-Ford en ese caso. 5 | struct edge{ 6 | int to, weight; 7 | edge() {} 8 | edge(int t, int w) : to(t), weight(w) {} 9 | bool operator < (const edge &that) const { 10 | return weight > that.weight; 11 | } 12 | }; 13 | 14 | vector g[MAXNODES]; 15 | // g[i] es la lista de aristas salientes del nodo i. Cada una 16 | // indica hacia que nodo va (to) y su peso (weight). Para 17 | // aristas bidireccionales se deben crear 2 aristas dirigidas. 18 | 19 | // encuentra el camino más corto entre s y todos los demás 20 | // nodos. 21 | int d[MAXNODES]; //d[i] = distancia más corta desde s hasta i 22 | int p[MAXNODES]; //p[i] = predecesor de i en la ruta más corta 23 | int dijkstra(int s, int n){ 24 | //s = nodo inicial, n = número de nodos 25 | for (int i=0; i q; 31 | q.push(edge(s, 0)); 32 | while (!q.empty()){ 33 | int node = q.top().to; 34 | int dist = q.top().weight; 35 | q.pop(); 36 | 37 | if (dist > d[node]) continue; 38 | if (node == t){ 39 | //dist es la distancia más corta hasta t. 40 | //Para reconstruir la ruta se pueden seguir 41 | //los p[i] hasta que sea -1. 42 | return dist; 43 | } 44 | 45 | for (int i=0; i g[MAXN+1]; //Vecinos de cada nodo. 8 | inline void link(int u, int v, int c) 9 | { cap[u][v] = c; g[u].push_back(v), g[v].push_back(u); } 10 | /* 11 | Notar que link crea las aristas (u, v) && (v, u) en el grafo 12 | g. Esto es necesario porque el algoritmo de Edmonds-Karp 13 | necesita mirar el "back-edge" (j, i) que se crea al bombear 14 | flujo a través de (i, j). Sin embargo, no modifica 15 | cap[v][u], porque se asume que el grafo es dirigido. Si es 16 | no-dirigido, hacer cap[u][v] = cap[v][u] = c. 17 | */ 18 | 19 | 20 | /* 21 | Método 1: 22 | 23 | Mantener la red residual, donde residual[i][j] = cuánto 24 | flujo extra puedo inyectar a través de la arista (i, j). 25 | 26 | Si empujo k unidades de i a j, entonces residual[i][j] -= k 27 | y residual[j][i] += k (Puedo "desempujar" las k unidades de 28 | j a i). 29 | 30 | Se puede modificar para que no utilice extra memoria en la 31 | tabla residual, sino que modifique directamente la tabla 32 | cap. 33 | */ 34 | 35 | int residual[MAXN+1][MAXN+1]; 36 | int fordFulkerson(int n, int s, int t){ 37 | memcpy(residual, cap, sizeof cap); 38 | 39 | int ans = 0; 40 | while (true){ 41 | fill(prev, prev+n, -1); 42 | queue q; 43 | q.push(s); 44 | while (q.size() && prev[t] == -1){ 45 | int u = q.front(); 46 | q.pop(); 47 | vector &out = g[u]; 48 | for (int k = 0, m = out.size(); k 0) 51 | prev[v] = u, q.push(v); 52 | } 53 | } 54 | 55 | if (prev[t] == -1) break; 56 | 57 | int bottleneck = INT_MAX; 58 | for (int v = t, u = prev[v]; u != -1; v = u, u = prev[v]){ 59 | bottleneck = min(bottleneck, residual[u][v]); 60 | } 61 | for (int v = t, u = prev[v]; u != -1; v = u, u = prev[v]){ 62 | residual[u][v] -= bottleneck; 63 | residual[v][u] += bottleneck; 64 | } 65 | ans += bottleneck; 66 | } 67 | return ans; 68 | } 69 | 70 | 71 | 72 | /* 73 | Método 2: 74 | 75 | Mantener la red de flujos, donde flow[i][j] = Flujo que, 76 | err, fluye de i a j. Notar que flow[i][j] puede ser 77 | negativo. Si esto pasa, es lo equivalente a decir que i 78 | "absorbe" flujo de j, o lo que es lo mismo, que hay flujo 79 | positivo de j a i. 80 | 81 | En cualquier momento se cumple la propiedad de skew 82 | symmetry, es decir, flow[i][j] = -flow[j][i]. El flujo neto 83 | de i a j es entonces flow[i][j]. 84 | */ 85 | 86 | int flow[MAXN+1][MAXN+1]; 87 | int fordFulkerson(int n, int s, int t){ 88 | //memset(flow, 0, sizeof flow); 89 | for (int i=0; i q; 94 | q.push(s); 95 | while (q.size() && prev[t] == -1){ 96 | int u = q.front(); 97 | q.pop(); 98 | vector &out = g[u]; 99 | for (int k = 0, m = out.size(); k flow[u][v]) 102 | prev[v] = u, q.push(v); 103 | } 104 | } 105 | 106 | if (prev[t] == -1) break; 107 | 108 | int bottleneck = INT_MAX; 109 | for (int v = t, u = prev[v]; u != -1; v = u, u = prev[v]){ 110 | bottleneck = min(bottleneck, cap[u][v] - flow[u][v]); 111 | } 112 | for (int v = t, u = prev[v]; u != -1; v = u, u = prev[v]){ 113 | flow[u][v] += bottleneck; 114 | flow[v][u] = -flow[u][v]; 115 | } 116 | ans += bottleneck; 117 | } 118 | return ans; 119 | } 120 | 121 | -------------------------------------------------------------------------------- /src/grafos/ford_fulkerson_sparse.cpp: -------------------------------------------------------------------------------- 1 | /////////////// Maximum flow for sparse graphs /////////////// 2 | /////////////// Complexity: O(V * E^2) /////////////// 3 | 4 | /* 5 | Usage: 6 | Call initialize_max_flow(); 7 | Create graph using add_edge(u, v, c); 8 | max_flow(source, sink); 9 | 10 | WARNING: The algorithm writes on the cap array. The capacity 11 | is not the same after having run the algorithm. If you need 12 | to run the algorithm several times on the same graph, backup 13 | the cap array. 14 | */ 15 | 16 | namespace Flow { 17 | // Maximum number of nodes 18 | const int MAXN = 100; 19 | // Maximum number of edges 20 | // IMPORTANT: Remember to consider the backedges. For 21 | // every edge we actually need two! That's why we have 22 | // to multiply by two at the end. 23 | const int MAXE = MAXN * (MAXN + 1) / 2 * 2; 24 | const int oo = INT_MAX / 4; 25 | int first[MAXN], next[MAXE], adj[MAXE], cap[MAXE]; 26 | int current_edge; 27 | 28 | /* 29 | Builds a directed edge (u, v) with capacity c. 30 | Note that actually two edges are added, the edge 31 | and its complementary edge for the backflow. 32 | */ 33 | int add_edge(int u, int v, int c){ 34 | adj[current_edge] = v; 35 | cap[current_edge] = c; 36 | next[current_edge] = first[u]; 37 | first[u] = current_edge++; 38 | 39 | adj[current_edge] = u; 40 | cap[current_edge] = 0; 41 | next[current_edge] = first[v]; 42 | first[v] = current_edge++; 43 | } 44 | 45 | void initialize_max_flow(){ 46 | current_edge = 0; 47 | memset(next, -1, sizeof next); 48 | memset(first, -1, sizeof first); 49 | } 50 | 51 | int q[MAXN]; 52 | int incr[MAXN]; 53 | int arrived_by[MAXN]; 54 | //arrived_by[i] = The last edge used to reach node i 55 | int find_augmenting_path(int src, int snk){ 56 | /* 57 | Make a BFS to find an augmenting path from the source 58 | to the sink. Then pump flow through this path, and 59 | return the amount that was pumped. 60 | */ 61 | memset(arrived_by, -1, sizeof arrived_by); 62 | int h = 0, t = 0; 63 | q[t++] = src; 64 | arrived_by[src] = -2; 65 | incr[src] = oo; 66 | while (h < t && arrived_by[snk] == -1){ //BFS 67 | int u = q[h++]; 68 | for (int e = first[u]; e != -1; e = next[e]){ 69 | int v = adj[e]; 70 | if (arrived_by[v] == -1 && cap[e] > 0){ 71 | arrived_by[v] = e; 72 | incr[v] = min(incr[u], cap[e]); 73 | q[t++] = v; 74 | } 75 | } 76 | } 77 | 78 | if (arrived_by[snk] == -1) return 0; 79 | 80 | int cur = snk; 81 | int neck = incr[snk]; 82 | while (cur != src){ 83 | //Remove capacity from the edge used to reach 84 | //node "cur", and add capacity to the backedge 85 | cap[arrived_by[cur]] -= neck; 86 | cap[arrived_by[cur] ^ 1] += neck; 87 | //move backwards in the path 88 | cur = adj[arrived_by[cur] ^ 1]; 89 | } 90 | return neck; 91 | } 92 | 93 | int max_flow(int src, int snk){ 94 | int ans = 0, neck; 95 | while ((neck = find_augmenting_path(src, snk)) != 0){ 96 | ans += neck; 97 | } 98 | return ans; 99 | } 100 | } -------------------------------------------------------------------------------- /src/grafos/highlight.sh: -------------------------------------------------------------------------------- 1 | source-highlight -i $1.cpp -o $1.tex -s cpp -f latexcolor 2 | 3 | -------------------------------------------------------------------------------- /src/grafos/konig.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int L, R, int matchL[MAXN], matchR[MAXN]; 3 | bitset seenL, seenR; 4 | vector g[MAXN]; 5 | 6 | void dfs(int u) { // u is on L 7 | if (u == -1 or seenL[u]) return; 8 | seenL[u] = true; 9 | foreach(out, g[u]) { 10 | int v = *out; 11 | if (!seenR[v]) { 12 | seenR[v] = true; 13 | dfs(matchR[v]); 14 | } 15 | } 16 | } 17 | 18 | // Build the maximum bipartite matching first! 19 | void minimumVertexCover() { 20 | int size = 0; 21 | for (int i = 0; i < L; ++i) { 22 | if (matchL[i] == -1) dfs(i); 23 | else size++; 24 | } 25 | // size == size of the minimum vertex cover. 26 | // The actual mininum vertex cover is formed by: 27 | // + nodes in L such that seenL[i] == false 28 | // + nodes in R such that seenR[i] == true 29 | } -------------------------------------------------------------------------------- /src/grafos/kruskal.cpp: -------------------------------------------------------------------------------- 1 | //Complejidad: O(E log V) 2 | struct edge{ 3 | int start, end, weight; 4 | bool operator < (const edge &that) const { 5 | //Si se desea encontrar el árbol de recubrimiento de 6 | //máxima suma, cambiar el < por un > 7 | return weight < that.weight; 8 | } 9 | }; 10 | 11 | 12 | ///////////////// Empieza Union find //////////////////////// 13 | //Complejidad: O(m log n), donde m es el número de operaciones 14 | //y n es el número de objetos. En la práctica la complejidad 15 | //es casi que O(m). 16 | int p[MAXNODES], rank[MAXNODES]; 17 | void make_set(int x){ p[x] = x, rank[x] = 0; } 18 | void link(int x, int y){ 19 | if (rank[x] > rank[y]) p[y] = x; 20 | else{ p[x] = y; if (rank[x] == rank[y]) rank[y]++; } 21 | } 22 | int find_set(int x){ 23 | return x != p[x] ? p[x] = find_set(p[x]) : p[x]; 24 | } 25 | void merge(int x, int y){ link(find_set(x), find_set(y)); } 26 | ///////////////// Termina Union find //////////////////////// 27 | 28 | //e es un vector con todas las aristas del grafo ¡El grafo 29 | //debe ser no digirido! 30 | long long kruskal(const vector &e){ 31 | long long total = 0; 32 | sort(e.begin(), e.end()); 33 | for (int i=0; i<=n; ++i){ 34 | make_set(i); 35 | } 36 | for (int i=0; i up[MAXN]; 18 | vector g[MAXN]; 19 | // alternatively, you can use a global graph to save space. 20 | // This graph is only used inside LCA::dfs below. 21 | 22 | int L, timer; 23 | 24 | void clear(int n) { 25 | for (int i = 0; i < n; ++i) g[i].clear(); 26 | } 27 | void add_edge(int u, int v) { 28 | g[u].push_back(v); 29 | g[v].push_back(u); 30 | } 31 | void dfs(int v, int p) { 32 | tin[v] = ++timer; 33 | up[v][0] = p; 34 | for (int i = 1; i <= L; ++i) 35 | up[v][i] = up[up[v][i-1]][i-1]; 36 | for (int i = 0; i < g[v].size(); ++i) { 37 | int to = g[v][i]; 38 | if (to != p) dfs(to, v); 39 | } 40 | tout[v] = ++timer; 41 | } 42 | inline bool upper(int a, int b) { 43 | return tin[a] <= tin[b] && tout[b] <= tout[a]; 44 | } 45 | int lca(int a, int b) { 46 | if (upper(a, b)) return a; 47 | if (upper(b, a)) return b; 48 | for (int i = L; i >= 0; --i) 49 | if (!upper(up[a][i], b)) 50 | a = up[a][i]; 51 | return up[a][0]; 52 | } 53 | void preprocess(int n, int root) { 54 | L = 1; 55 | while ((1 << L) <= n) ++L; 56 | for (int i = 0; i < n; ++i) up[i].resize(L + 1); 57 | timer = 0; 58 | dfs(root, root); 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /src/grafos/maximum_bipartite_matching.cpp: -------------------------------------------------------------------------------- 1 | // Maximum Bipartite Matching 2 | // Complexity: O(VE) 3 | 4 | // Finds a maximum bipartite matching for two sets of 5 | // size L and R. 6 | 7 | // How to use: 8 | // Set g[i][j] to true if element i of the Left set can 9 | // be paired with element j of the Right set. 10 | // Fill the table for all 0 <= i < L and 0 <= j < R. 11 | 12 | // matchL[i] will contain i's match in the Right set 13 | // and matchR[j] will contain j's match in the Left set. 14 | 15 | bool g[MAXN][MAXN], seen[MAXN]; 16 | int L, R, matchL[MAXN], matchR[MAXN]; 17 | 18 | bool assign(int i) { 19 | for (int j = 0; j < R; ++j) if (g[i][j] and !seen[j]) { 20 | seen[j] = true; 21 | if ( matchR[j] < 0 or assign(matchR[j]) ) 22 | return matchL[i] = j, matchR[j] = i, true; 23 | } 24 | return false; 25 | } 26 | 27 | int maxBipartiteMatching() { 28 | for (int i = 0; i < L; ++i) matchL[i] = -1; 29 | for (int j = 0; j < R; ++j) matchR[j] = -1; 30 | int ans = 0; 31 | for (int i = 0; i < L; ++i) { 32 | for (int j = 0; j < R; ++j) seen[j] = false; // or memset 33 | if (assign(i)) ans++; 34 | } 35 | return ans; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/grafos/min_cost_max_flow.cpp: -------------------------------------------------------------------------------- 1 | struct MCMF { 2 | typedef int ctype; 3 | enum { MAXN = 1000, INF = INT_MAX }; 4 | struct Edge { int x, y; ctype cap, cost; }; 5 | vector E; vector adj[MAXN]; 6 | int N, prev[MAXN]; ctype dist[MAXN], phi[MAXN]; 7 | 8 | MCMF(int NN) : N(NN) {} 9 | 10 | void add(int x, int y, ctype cap, ctype cost) { // cost >= 0 11 | Edge e1={x,y,cap,cost}, e2={y,x,0,-cost}; 12 | adj[e1.x].push_back(E.size()); E.push_back(e1); 13 | adj[e2.x].push_back(E.size()); E.push_back(e2); 14 | } 15 | 16 | void mcmf(int s, int t, ctype &flowVal, ctype &flowCost) { 17 | int x; 18 | flowVal = flowCost = 0; memset(phi, 0, sizeof(phi)); 19 | while (true) { 20 | for (x = 0; x < N; x++) prev[x] = -1; 21 | for (x = 0; x < N; x++) dist[x] = INF; 22 | dist[s] = prev[s] = 0; 23 | 24 | set< pair > Q; 25 | Q.insert(make_pair(dist[s], s)); 26 | while (!Q.empty()) { 27 | x = Q.begin()->second; Q.erase(Q.begin()); 28 | FOREACH(it, adj[x]) { 29 | const Edge &e = E[*it]; 30 | if (e.cap <= 0) continue; 31 | ctype cc = e.cost + phi[x] - phi[e.y]; // *** 32 | if (dist[x] + cc < dist[e.y]) { 33 | Q.erase(make_pair(dist[e.y], e.y)); 34 | dist[e.y] = dist[x] + cc; 35 | prev[e.y] = *it; 36 | Q.insert(make_pair(dist[e.y], e.y)); 37 | } 38 | } 39 | } 40 | if (prev[t] == -1) break; 41 | 42 | ctype z = INF; 43 | for (x = t; x != s; x = E[prev[x]].x) 44 | { z = min(z, E[prev[x]].cap); } 45 | for (x = t; x != s; x = E[prev[x]].x) 46 | { E[prev[x]].cap -= z; E[prev[x]^1].cap += z; } 47 | flowVal += z; 48 | flowCost += z * (dist[t] - phi[s] + phi[t]); 49 | for (x = 0; x < N; x++) 50 | { if (prev[x] != -1) phi[x] += dist[x]; } // *** 51 | } 52 | } 53 | }; -------------------------------------------------------------------------------- /src/grafos/prim.cpp: -------------------------------------------------------------------------------- 1 | //Complejidad: O(E log V) 2 | //¡El grafo debe ser no digirido! 3 | typedef string node; 4 | typedef pair edge; 5 | //edge.first = peso de la arista, edge.second = nodo al que se 6 | //dirige 7 | typedef map > graph; 8 | 9 | double prim(const graph &g){ 10 | double total = 0.0; 11 | priority_queue, greater > q; 12 | q.push(edge(0.0, g.begin()->first)); 13 | set visited; 14 | while (q.size()){ 15 | node u = q.top().second; 16 | double w = q.top().first; 17 | q.pop(); //!! 18 | if (visited.count(u)) continue; 19 | visited.insert(u); 20 | total += w; 21 | vector &vecinos = g[u]; 22 | for (int i=0; i > graph; 5 | typedef char color; 6 | const color WHITE = 0, GRAY = 1, BLACK = 2; 7 | graph g; 8 | map colors; 9 | map d, low; 10 | 11 | set cameras; //contendrá los puntos de articulación 12 | int timeCount; 13 | 14 | // Uso: Para cada nodo u: 15 | // colors[u] = WHITE, g[u] = Aristas salientes de u. 16 | // Funciona para grafos no dirigidos. 17 | 18 | void dfs(node v, bool isRoot = true){ 19 | colors[v] = GRAY; 20 | d[v] = low[v] = ++timeCount; 21 | const vector &neighbors = g[v]; 22 | int count = 0; 23 | for (int i=0; i= d[v]){ 28 | //current node is an articulation point 29 | cameras.insert(v); 30 | } 31 | low[v] = min(low[v], low[neighbors[i]]); 32 | ++count; 33 | }else{ // (v, neighbors[i]) is a back edge 34 | low[v] = min(low[v], d[neighbors[i]]); 35 | } 36 | } 37 | if (isRoot && count > 1){ 38 | //Is root and has two neighbors in the DFS-tree 39 | cameras.insert(v); 40 | } 41 | colors[v] = BLACK; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/grafos/tarjan.cpp: -------------------------------------------------------------------------------- 1 | /* Complexity: O(E + V) 2 | Tarjan's algorithm for finding strongly connected 3 | components. 4 | 5 | *d[i] = Discovery time of node i. (Initialize to -1) 6 | *low[i] = Lowest discovery time reachable from node 7 | i. (Doesn't need to be initialized) 8 | *scc[i] = Strongly connected component of node i. (Doesn't 9 | need to be initialized) 10 | *s = Stack used by the algorithm (Initialize to an empty 11 | stack) 12 | *stacked[i] = True if i was pushed into s. (Initialize to 13 | false) 14 | *ticks = Clock used for discovery times (Initialize to 0) 15 | *current_scc = ID of the current_scc being discovered 16 | (Initialize to 0) 17 | */ 18 | vector g[MAXN]; 19 | int d[MAXN], low[MAXN], scc[MAXN]; 20 | bool stacked[MAXN]; 21 | stack s; 22 | int ticks, current_scc; 23 | 24 | void tarjan(int u){ 25 | d[u] = low[u] = ticks++; 26 | s.push(u); 27 | stacked[u] = true; 28 | 29 | const vector &out = g[u]; 30 | for (int k=0, m=out.size(); k 0){ 13 | String a, b; 14 | a = reader.readLine(); 15 | b = reader.readLine(); 16 | 17 | int A = a.length(), B = b.length(); 18 | if (B > A){ 19 | System.out.println("0"); 20 | }else{ 21 | BigInteger dp[][] = new BigInteger[2][A]; 22 | /* 23 | dp[i][j] = cantidad de maneras diferentes 24 | en que puedo distribuir las primeras i 25 | letras de la subsecuencia (b) terminando 26 | en la letra j de la secuencia original (a) 27 | */ 28 | 29 | if (a.charAt(0) == b.charAt(0)){ 30 | dp[0][0] = BigInteger.ONE; 31 | }else{ 32 | dp[0][0] = BigInteger.ZERO; 33 | } 34 | for (int j=1; j m = new TreeMap(); 13 | HashMap m = new HashMap(); 14 | m.put("Hola", new Integer(465)); 15 | System.out.println("m.size() = " + m.size()); 16 | 17 | if (m.containsKey("Hola")) { 18 | System.out.println(m.get("Hola")); 19 | } 20 | 21 | System.out.println(m.get("Objeto inexistente")); 22 | 23 | /* 24 | * Sets 25 | * La misma diferencia entre TreeSet y HashSet. 26 | */ 27 | System.out.println("\nSets"); 28 | /* 29 | * *OJO: El HashSet no está en orden, el TreeSet sí. 30 | */ 31 | //HashSet s = new HashSet(); 32 | TreeSet < Integer > s = new TreeSet < Integer > (); 33 | s.add(3576); 34 | s.add(new Integer("54")); 35 | s.add(new Integer(1000000007)); 36 | 37 | if (s.contains(54)) { 38 | System.out.println("54 presente."); 39 | } 40 | 41 | if (s.isEmpty() == false) { 42 | System.out.println("s.size() = " + s.size()); 43 | Iterator < Integer > i = s.iterator(); 44 | while (i.hasNext()) { 45 | System.out.println(i.next()); 46 | i.remove(); 47 | } 48 | System.out.println("s.size() = " + s.size()); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/java/priority_queue.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | 4 | class Item implements Comparable{ 5 | int destino, peso; 6 | 7 | Item(int destino, int peso){ 8 | this.peso = peso; 9 | this.destino = destino; 10 | } 11 | /* 12 | * Implementamos toda la javazofia. 13 | */ 14 | public int compareTo(Item otro){ 15 | // Return < 0 si this < otro 16 | // Return 0 si this == otro 17 | // Return > 0 si this > otro 18 | /* Un nodo es menor que otro si tiene menos peso */ 19 | return peso - otro.peso; 20 | } 21 | public boolean equals(Object otro){ 22 | if (otro instanceof Item){ 23 | Item ese = (Item)otro; 24 | return destino == ese.destino && peso == ese.peso; 25 | } 26 | return false; 27 | } 28 | public String toString(){ 29 | return "peso = " + peso + ", destino = " + destino; 30 | } 31 | } 32 | 33 | class Ejemplo { 34 | public static void main(String[] args) { 35 | PriorityQueue q = new PriorityQueue(); 36 | q.add(new Item(12, 0)); 37 | q.add(new Item(4, 1876)); 38 | q.add(new Item(13, 0)); 39 | q.add(new Item(8, 0)); 40 | q.add(new Item(7, 3)); 41 | while (!q.isEmpty()){ 42 | System.out.println(q.poll()); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/misc/highlight.sh: -------------------------------------------------------------------------------- 1 | source-highlight -i $1.cpp -o $1.tex -s cpp -f latexcolor 2 | 3 | -------------------------------------------------------------------------------- /src/misc/josephus.cpp: -------------------------------------------------------------------------------- 1 | // Recursivo: 2 | // n <= 2500 3 | // Es O(n), pero mejor usar la versión iterativa 4 | // para evitar stack overflows. 5 | int joseph(int n, int k) { 6 | assert(n >= 1); 7 | if (n == 1) return 0; 8 | return (joseph(n - 1, k) + k) % n; 9 | } 10 | 11 | // Iterativo: 12 | // n <= 10^6, k <= 2^31 - 1 13 | int joseph(int n, int k) { 14 | int ans = 0; 15 | for (int i = 2; i <= n; ++i) { 16 | ans = (ans + k) % i; 17 | } 18 | return ans; 19 | } 20 | 21 | // Más rápido: 22 | // n <= 10^18, k <= 2500 23 | // Posiblemente se puede incrementar k un poco más 24 | // si se cambia la línea marcada con *** por la versión 25 | // iterativa, para evitar stack overflows. 26 | long long joseph(long long n, int k) { 27 | assert(n >= 1); 28 | if (n == 1) return 0LL; 29 | if (k == 1) return n - 1; 30 | if (n < k) return (joseph(n - 1, k) + k) % n; // *** 31 | long long w = joseph(n - n / k, k) - n % k; 32 | if (w < 0) return w + n; 33 | return w + w / (k - 1); 34 | } 35 | -------------------------------------------------------------------------------- /src/misc/knight_distance.cpp: -------------------------------------------------------------------------------- 1 | // Returns the number of moves a knight must make 2 | //to go from (x1, y1) to (x2, y2) in an INFINITE 3 | // chess board. 4 | long long knight_distance(long long x1, long long y1, 5 | long long x2, long long y2) { 6 | long long x = abs(x2 - x1), y = abs(y2 - y1); 7 | if (x > y) swap(x, y); 8 | assert(x <= y); 9 | if (x == 0 and y == 1) return 3; 10 | if (x == 2 and y == 2) return 4; 11 | long long d = max((y + 1) / 2, (x + y + 2) / 3); 12 | if (d % 2 != (x + y) % 2) d++; 13 | return d; 14 | } -------------------------------------------------------------------------------- /src/misc/parser_recursivo_desc.cpp: -------------------------------------------------------------------------------- 1 | //A -> (A)A | Epsilon 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | bool ok; 9 | char sgte; 10 | int i; 11 | string s; 12 | 13 | bool match(char c){ 14 | if (sgte != c){ 15 | ok = false; 16 | } 17 | sgte = s[++i]; 18 | } 19 | 20 | void A(){ 21 | if (sgte == '('){ 22 | match('('); 23 | A(); match(')'); A(); 24 | }else if (sgte == '$' || sgte == ')'){ 25 | //nada 26 | }else{ 27 | ok = false; 28 | } 29 | } 30 | 31 | int main(){ 32 | while(getline(cin, s) && s != ""){ 33 | ok = true; 34 | s += '$'; 35 | sgte = s[(i = 0)]; 36 | A(); 37 | if (i < s.length()-1) ok=false; //No consumí toda la cadena 38 | if (ok){ 39 | cout << "Accepted\n"; 40 | }else{ 41 | cout << "Not accepted\n"; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/misc/subsets_of_mask.cpp: -------------------------------------------------------------------------------- 1 | for(int m = mask; m > 0; m = (m-1) & mask){ 2 | // m tiene un subconjunto de mask 3 | } 4 | -------------------------------------------------------------------------------- /src/strings/dynamic_hashing.cpp: -------------------------------------------------------------------------------- 1 | // N = size of the array. It is assumed that elements are 2 | // indexed from 1 to N, inclusive. 3 | // B = the base for the hash. Must be > 0. 4 | // P = The modulo for the hash. Must be > 0. Doesn't need 5 | // to be prime. 6 | int N, B, P; 7 | 8 | int tree[MAXN], base[MAXN]; 9 | 10 | void precomputeBases() { 11 | base[0] = 1; 12 | for (int i = 1; i <= N + 1; ++i) { 13 | base[i] = (1LL * base[i - 1] * B) % P; 14 | } 15 | } 16 | 17 | inline int mod(long long a) { 18 | int ans = a % P; 19 | if (ans < 0) ans += P; 20 | return ans; 21 | } 22 | 23 | // Usually you don't want to use this function directly, 24 | // use 'put' below instead. 25 | void add(int at, int what) { 26 | what = mod(what); 27 | int seen = 0; 28 | for (at++; at <= N + 1; at += at & -at) { 29 | tree[at] += (1LL * what * base[seen]) % P; 30 | tree[at] = mod(tree[at]); 31 | seen += at & -at; 32 | } 33 | } 34 | 35 | // Returns the hash for subarray [1..at]. 36 | int query(int at) { 37 | int ans = 0, seen = 0; 38 | for (at++; at > 0; at -= at & -at) { 39 | ans += (1LL * tree[at] * base[seen]) % P; 40 | ans = mod(ans); 41 | seen += at & -at; 42 | } 43 | return ans; 44 | } 45 | 46 | // Returns the hash for subarray [i..j]. That hash is: 47 | // a[i]*B^(j-i+1) + a[i+1]*Bˆ(j-i) + a[i+2]*B^(j-i-1) + ... 48 | // + a[j-2]*B^2 + a[j-1]*B^1 + a[j]*B^0 (mod P) 49 | int hash(int i, int j) { 50 | assert(i <= j); 51 | int ans = query(j) - (1LL * query(i-1) * base[j-i+1]) % P; 52 | return mod(ans); 53 | } 54 | 55 | // Changes the number or char at position 'at' for 'what'. 56 | void put(int at, int what) { 57 | add(at, -hash(at, at) + what); 58 | } 59 | -------------------------------------------------------------------------------- /src/strings/kmp.cpp: -------------------------------------------------------------------------------- 1 | // Knuth-Morris-Pratt algorithm for string matching 2 | // Complexity: O(n + m) 3 | 4 | // Reports all occurrences of 'needle' in 'haystack'. 5 | void kmp(const string &needle, const string &haystack) { 6 | // Precompute border function 7 | int m = needle.size(); 8 | vector border(m); 9 | border[0] = 0; 10 | for (int i = 1; i < m; ++i) { 11 | border[i] = border[i - 1]; 12 | while (border[i] > 0 and needle[i] != needle[border[i]]) { 13 | border[i] = border[border[i] - 1]; 14 | } 15 | if (needle[i] == needle[border[i]]) border[i]++; 16 | } 17 | 18 | // Now the actual matching 19 | int n = haystack.size(); 20 | int seen = 0; 21 | for (int i = 0; i < n; ++i){ 22 | while (seen > 0 and haystack[i] != needle[seen]) { 23 | seen = border[seen - 1]; 24 | } 25 | if (haystack[i] == needle[seen]) seen++; 26 | 27 | if (seen == m) { 28 | printf("Needle occurs from %d to %d\n", i - m + 1, i); 29 | seen = border[m - 1]; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/strings/manacher.cpp: -------------------------------------------------------------------------------- 1 | // Complejidad: O(n) 2 | void manacher(const string &s) { 3 | int n = s.size(); 4 | 5 | vector d1(n); 6 | int l=0, r=-1; 7 | for (int i=0; ir ? 0 : min (d1[l+r-i], r-i)) + 1; 9 | while (i+k < n && i-k >= 0 && s[i+k] == s[i-k]) ++k; 10 | d1[i] = --k; 11 | if (i+k > r) l = i-k, r = i+k; 12 | } 13 | vector d2(n); 14 | l=0, r=-1; 15 | for (int i=0; ir ? 0 : min (d2[l+r-i+1], r-i+1)) + 1; 17 | while (i+k-1 < n && i-k >= 0 && s[i+k-1] == s[i-k]) ++k; 18 | d2[i] = --k; 19 | if (i+k-1 > r) l = i-k, r = i+k-1; 20 | } 21 | 22 | // d1[i] = piso de la mitad de la longitud del palíndromo 23 | // impar más largo cuyo centro es i. 24 | // d2[i] = mitad de la longitud del palíndromo par más 25 | // largo cuyo centro de la derecha es i. 26 | 27 | for (int i = 0; i < n; ++i) { 28 | assert(is_palindrome( s.substr(i - d1[i], 2*d1[i] + 1) )); 29 | assert(is_palindrome( s.substr(i - d2[i], 2*d2[i]) )); 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /src/strings/minimum_rotation.cpp: -------------------------------------------------------------------------------- 1 | // Finds the lexicographically smallest rotation of string s. 2 | // Returns the index that should be moved to the first position 3 | // to achieve the smallest rotation. 4 | // If there are two or more smallest rotations, returns the 5 | // smallest index. 6 | int minimum_rotation(string s) { 7 | int n = s.size(); 8 | s = s + s; 9 | int mini = 0, p = 1, k = 0; 10 | while (p < n && mini + k + 1 < n) { 11 | if (s[mini + k] == s[p + k]) { 12 | k++; 13 | } else if (s[mini + k] < s[p + k]) { 14 | p = p + k + 1; 15 | k = 0; 16 | } else if (s[mini + k] > s[p + k]){ 17 | mini = max(mini + k + 1, p); 18 | p = mini + 1; 19 | k = 0; 20 | } 21 | } 22 | // the actual minimum rotated string is s.substr(mini, n) 23 | return mini; 24 | } -------------------------------------------------------------------------------- /src/strings/z_algorithm.cpp: -------------------------------------------------------------------------------- 1 | // Find z function 2 | int n = s.size(); 3 | vector z(n); 4 | z[0] = 0; 5 | for (int i = 1, l = 0, r = 0; i < n; ++i) { 6 | z[i] = 0; 7 | if (i <= r) z[i] = min(z[i - l], r - i + 1); 8 | while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; 9 | if (i + z[i] - 1 > r) { 10 | l = i; 11 | r = i + z[i] - 1; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/template.cpp: -------------------------------------------------------------------------------- 1 | #define _GLIBCXX_DEBUG 2 | using namespace std; 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | template string toStr(const T &x) 21 | { stringstream s; s << x; return s.str(); } 22 | template int toInt(const T &x) 23 | { stringstream s; s << x; int r; s >> r; return r; } 24 | 25 | #define For(i, a, b) for (int i=(a); i<(b); ++i) 26 | #define foreach(x, v) for (typeof (v).begin() x = (v).begin(); \ 27 | x != (v).end(); ++x) 28 | #define D(x) cout << #x " = " << (x) << endl 29 | 30 | const double EPS = 1e-9; 31 | int cmp(double x, double y = 0, double tol = EPS){ 32 | return( x <= y + tol) ? (x + tol < y) ? -1 : 0 : 1; 33 | } 34 | 35 | #define INPUT_FILE "problemname" 36 | 37 | int main(){ 38 | freopen(INPUT_FILE ".in", "r", stdin); // Read from file 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /src/teoria_de_numeros/bigmod.cpp: -------------------------------------------------------------------------------- 1 | //retorna (b^p)mod(m) 2 | // 0 <= b,p <= 2147483647 3 | // 1 <= m <= 46340 4 | int bigmod(int b, int p, int m){ 5 | int mask = 1; 6 | int pow2 = b % m; 7 | int r = 1; 8 | while (mask){ 9 | if (p & mask) r = (r * pow2) % m; 10 | pow2 = (pow2 * pow2) % m; 11 | mask <<= 1; 12 | } 13 | return r; 14 | } 15 | // Si se cambian los int por long longs los 16 | // valores de entrada deben cumplir: 17 | // 0 <= b,p <= 9223372036854775807 18 | // 1 <= m <= 3037000499 19 | // Si se cambian por unsigned long longs: 20 | // 0 <= b,p <= 18446744073709551615 21 | // 1 <= m <= 4294967295 22 | 23 | 24 | // Versión recursiva 25 | int bigMod(int b, int p, int m){ 26 | if(p == 0) return 1; 27 | if (p % 2 == 0){ 28 | int x = bigMod(b, p / 2, m); 29 | return (x * x) % m; 30 | } 31 | return ((b % m) * bigMod(b, p-1, m)) % m; 32 | } 33 | -------------------------------------------------------------------------------- /src/teoria_de_numeros/criba.cpp: -------------------------------------------------------------------------------- 1 | // Complejidad: O(n) 2 | 3 | const int LIMIT = 31622779; 4 | 5 | int sieve[LIMIT + 1]; // Inicializar con 0's. 6 | int primes[LIMIT + 1]; 7 | 8 | int primeCount = 1; 9 | for (int i = 2; i <= LIMIT; ++i) { 10 | if (!sieve[i]) { 11 | primes[primeCount] = i; 12 | sieve[i] = primeCount; 13 | primeCount++; 14 | } 15 | 16 | for (int j = 1; j <= sieve[i] && i * primes[j] <= LIMIT; j++){ 17 | sieve[ i * primes[j] ] = j; 18 | } 19 | } 20 | 21 | // primes contiene la lista de primos <= LIMIT, en los índices 22 | // 1 a primeCount. 23 | // ¡El primer primo está en la posición 1 y no 0! 24 | 25 | // sieve[i] contiene el índice en el arreglo primes del primo 26 | // más pequeño que divide a i. Con esta información se puede 27 | // saber si un número es primo o descomponerlo en primos si es 28 | // compuesto. 29 | 30 | // i es primo si primes[sieve[i]] == i, y compuesto si no. -------------------------------------------------------------------------------- /src/teoria_de_numeros/divisores.cpp: -------------------------------------------------------------------------------- 1 | for (int i=1; i*i<=n; i++) { 2 | if (n%i == 0) { 3 | cout << i << endl; 4 | if (i*i 0. 2 | // Returns v such that a * v == 1 (mod n). 3 | long long mod_inverse(long long a, long long n) { 4 | long long i = n, v = 0, d = 1; 5 | while (a > 0) { 6 | long long t = i / a, x = a; 7 | a = i % x; 8 | i = x; 9 | x = d; 10 | d = v - t * x; 11 | v = x; 12 | } 13 | v %= n; 14 | if (v < 0) v += n; 15 | return v; 16 | } 17 | --------------------------------------------------------------------------------