├── .gitignore
├── LICENSE
├── README.md
├── algorithms
├── adhoc
│ ├── date.h
│ └── timest.h
├── brute_force
│ └── next_combination.h
├── data_structures
│ ├── fenwick_tree.h
│ ├── product_fenwick_tree.h
│ ├── segment_tree.h
│ ├── segment_tree_bottom_up.h
│ ├── segment_tree_with_lazy_propagation.h
│ └── union_find.h
├── dp
│ ├── lis.h
│ ├── main_lis.cpp
│ ├── max1Drangesum.h
│ ├── max2Drangesum.h
│ └── max3Drangesum.h
├── geometry
│ ├── circle.h
│ ├── line.h
│ ├── point.h
│ └── triangle.h
├── graph
│ ├── 247.cpp
│ ├── 315.cpp
│ ├── bfs.h
│ ├── bipartite.h
│ ├── connected_components.h
│ ├── dfs.h
│ ├── dfs_topsort.h
│ ├── edmonds_karp.h
│ ├── graph.h
│ ├── graph_check.h
│ ├── has_cycle.h
│ ├── kruskall.h
│ ├── prim.h
│ └── tarjan_scc.h
└── io
│ ├── BufferedIO.java
│ ├── IO.java
│ ├── async_io.h
│ ├── buffered_io.h
│ ├── cio.h
│ └── io.h
├── tests
├── adhoc
│ ├── Makefile
│ ├── date.cpp
│ └── timest.cpp
├── brute_force
│ ├── Makefile
│ └── next_combination.cpp
├── catch.hpp
├── data_structures
│ ├── Makefile
│ ├── segment_tree.cpp
│ ├── segment_tree_bottom_up.cpp
│ └── segment_tree_with_lazy_propagation.cpp
├── geometry
│ ├── Makefile
│ ├── circle.cpp
│ ├── line.cpp
│ └── point.cpp
├── graph
│ ├── Makefile
│ ├── bfs.cpp
│ ├── bipartite.cpp
│ ├── connected_components.cpp
│ ├── dfs.cpp
│ └── has_cycle.cpp
└── io
│ ├── Makefile
│ ├── TestBufferedIO.java
│ ├── TestIO.java
│ ├── async_io.cpp
│ ├── buffered_io.cpp
│ ├── cio.c
│ ├── ints_100K.in
│ ├── ints_1M.in
│ └── io.cpp
└── util
└── bitwise_operations.h
/.gitignore:
--------------------------------------------------------------------------------
1 | *.cc
2 | *.class
3 | *.o
4 | *.swp
5 | *.exe
6 | prog
7 | out.txt
8 | elapsed.txt
9 | files
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
167 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Algoritmos
2 |
3 | Códigos para estudo e ensino.
4 |
5 | As classes são codificadas de modo que possam ser copiadas e coladas para uso em resolução de
6 | problemas de programação competitiva. Deste modo, são feitas algumas concessões em relação às
7 | boas práticas de Engenharia de Software (uso de variáveis globais, implementação nos _headers_,
8 | etc) para atingir tal fim. Logo, as classes não visam o reuso e a aplicação em ambientes de
9 | produção.
10 |
--------------------------------------------------------------------------------
/algorithms/adhoc/date.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe para a representação de datas (em dias, meses e anos).
3 | *
4 | * Autor: Edson Alves
5 | * Data: 25/03/2015
6 | * Licença: LGPL. Sem copyright.
7 | */
8 | #ifndef DATE_H
9 | #define DATE_H
10 |
11 | #include
12 |
13 | static const int days_in_month_regular[] {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
14 | static const int days_in_month_leap[] {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
15 |
16 | class Date {
17 | public:
18 | Date(int d = 0, int m = 0, int y = 0) : m_d(d), m_m(m), m_y(y) { }
19 |
20 | void add(int days)
21 | {
22 | long long date_days = days_from_zero(m_d, m_m, m_y);
23 | date_days += days;
24 | date_from_days(date_days, m_d, m_m, m_y);
25 | }
26 |
27 | int day() const { return m_d; }
28 | int month() const { return m_m; }
29 | int year() const { return m_y; }
30 |
31 | std::string format() const
32 | {
33 | char buffer[32];
34 | sprintf(buffer, "%02d/%02d/%04d", m_d, m_m, m_y);
35 |
36 | return std::string(buffer);
37 | }
38 |
39 | long long operator-(const Date& d) const
40 | {
41 | return days_from_zero(m_d, m_m, m_y) - days_from_zero(d.day(), d.month(), d.year());
42 | }
43 |
44 | static bool is_leap(int year)
45 | {
46 | return (year % 400 == 0) or (year % 4 == 0 and year % 100 != 0);
47 | }
48 |
49 | static Date from_days(long long days)
50 | {
51 | int d, m, y;
52 | date_from_days(days, d, m, y);
53 | return Date(d, m, y);
54 | }
55 |
56 | private:
57 | int m_d, m_m, m_y;
58 |
59 | static int leaps(int y)
60 | {
61 | int div4 = y / 4;
62 | int div100 = y / 100;
63 | int div400 = y / 400;
64 |
65 | return div4 - div100 + div400;
66 | }
67 |
68 | static long long days_from_zero(int d, int m, int y)
69 | {
70 | long long days = d;
71 | const int *days_in_month = Date::is_leap(y) ? days_in_month_leap : days_in_month_regular;
72 |
73 | for (int i = 1; i < m; i++)
74 | days += days_in_month[i];
75 |
76 | int leap_years = leaps(y - 1);
77 | days += 365*y + leap_years;
78 |
79 | return days;
80 | }
81 |
82 | static void date_from_days(int days, int& d, int &m, int& y)
83 | {
84 | y = days / 366;
85 |
86 | while (days_from_zero(0, 0, y + 1) < days)
87 | y++;
88 |
89 | days -= days_from_zero(0, 0, y);
90 |
91 | const int *days_in_month = Date::is_leap(y) ? days_in_month_leap : days_in_month_regular;
92 |
93 | m = 1;
94 |
95 | while (days > days_in_month[m])
96 | {
97 | days -= days_in_month[m];
98 | m++;
99 | }
100 |
101 | d = days;
102 | }
103 | };
104 |
105 | #endif
106 |
--------------------------------------------------------------------------------
/algorithms/adhoc/timest.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe para a representação de tempo (em horas, minutos e segundos).
3 | *
4 | * Autor: Edson Alves
5 | * Data: 24/03/2015
6 | * Licença: LGPL. Sem copyright.
7 | */
8 | #ifndef TIMEST_H
9 | #define TIMEST_H
10 |
11 | #include
12 |
13 | const int SECS_IN_A_DAY { 86400 };
14 | const int SECS_IN_A_HOUR { 3600 };
15 | const int SECS_IN_A_MIN { 60 };
16 |
17 | class Time {
18 | public:
19 | Time(int h = 0, int m = 0, int s = 0)
20 | {
21 | m_secs = SECS_IN_A_HOUR*h + SECS_IN_A_MIN*m + s;
22 | }
23 |
24 | int hours() const
25 | {
26 | int h = m_secs / SECS_IN_A_HOUR;
27 | return h;
28 | }
29 |
30 | int minutes() const
31 | {
32 | int m = (m_secs % SECS_IN_A_HOUR) / SECS_IN_A_MIN;
33 | return m;
34 | }
35 |
36 | int seconds() const
37 | {
38 | int s = m_secs % SECS_IN_A_MIN;
39 | return s;
40 | }
41 |
42 | void add(const Time& t)
43 | {
44 | m_secs += t.m_secs;
45 | m_secs %= SECS_IN_A_DAY;
46 | }
47 |
48 | std::string format() const
49 | {
50 | char buffer[32];
51 | sprintf(buffer, "%02d:%02d:%02d", hours(), minutes(), seconds());
52 |
53 | return std::string(buffer);
54 | }
55 |
56 | private:
57 | int m_secs;
58 | };
59 |
60 | #endif
61 |
--------------------------------------------------------------------------------
/algorithms/brute_force/next_combination.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Rotina que gera as C(n, m) combinações.
3 | *
4 | * Baseada no artigo The Coolest Way To Generate Combinations, de Frank Ruskey e Aaron Williams.
5 | * Uma combinação será representada por uma string s de zeros e uns, onde s[i] = 1 indica que o
6 | * elemento i pertence à combinação. Cada combinação é gerada em O(1): a estratégia de chamar
7 | * prev_permutation() a partir da string inicial s = "11111...100000" tem complexidade O(n) por
8 | * combinação.
9 | *
10 | * Autor: Edson Alves
11 | * Data: 11/05/2018
12 | * Licença: LGPL. Sem copyright.
13 | */
14 | #ifndef COMBINATIONS_H
15 | #define COMBINATIONS_H
16 |
17 | #include
18 |
19 | // Na primeira chamada, a string combination deve ser nula (size == 0)
20 | bool next_combination(int n, int m, std::string& combination, int& x, int& y)
21 | {
22 | // Caso base: primeira combinação
23 | if (combination.empty())
24 | {
25 | combination = std::string(m, '1');
26 | combination.resize(n, '0');
27 |
28 | x = -1;
29 | y = -1;
30 |
31 | return true;
32 | }
33 |
34 | // Caso base: inicialização de x e y
35 | if (y == -1)
36 | {
37 | combination[m] = '1';
38 | combination[0] = '0';
39 | x = 1;
40 | y = 0;
41 |
42 | return true;
43 | }
44 |
45 | // Caso base: não há mais combinações
46 | if (x == n - 1)
47 | return false;
48 |
49 | combination[x] = '0';
50 | combination[y] = '1';
51 | combination[0] = combination[x + 1];
52 | combination[x + 1] = '1';
53 |
54 | x = x * (1 - (combination[1] - '0') + (combination[1] - '0')*(combination[0] - '0')) + 1;
55 | y = (y + 1)*(combination[0] - '0');
56 |
57 | return true;
58 | }
59 |
60 | #endif
61 |
--------------------------------------------------------------------------------
/algorithms/data_structures/fenwick_tree.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe Fenwick (BIT) Tree
3 | *
4 | * Esta versão mais simples suporta Point Updates com Range Queries.
5 | *
6 | * Autor: Edson Alves
7 | * Data: 04/09/2015
8 | * Licença: LGPL. Sem copyright.
9 | */
10 | #ifndef FENWICK_TREE_H
11 | #define FENWICK_TREE_H
12 |
13 | #include
14 |
15 | using namespace std;
16 |
17 | typedef long long ll;
18 |
19 | #define FENWICK_TREE_MAX 1000005
20 |
21 | ll tree[FENWICK_TREE_MAX];
22 |
23 | inline ll least_significative_bit(ll n) { return n & (-n); }
24 |
25 | class FenwickTree
26 | {
27 | public:
28 | FenwickTree(ll N)
29 | : m_N(N)
30 | {
31 | memset(tree, 0, (N + 1) * sizeof(ll));
32 | }
33 |
34 | ll RSQ(ll a, ll b)
35 | {
36 | return a == 1 ? RSQ(b) : RSQ(b) - RSQ(a - 1);
37 | }
38 |
39 | void update(ll k, ll v)
40 | {
41 | while (k <= m_N)
42 | {
43 | tree[k] += v;
44 | k += least_significative_bit(k);
45 | }
46 | }
47 |
48 | private:
49 | ll RSQ(ll b)
50 | {
51 | ll sum = 0;
52 |
53 | while (b)
54 | {
55 | sum += tree[b];
56 | b -= least_significative_bit(b);
57 | }
58 |
59 | return sum;
60 | }
61 |
62 | private:
63 | ll m_N;
64 | };
65 |
66 | #endif
67 |
--------------------------------------------------------------------------------
/algorithms/data_structures/product_fenwick_tree.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe Fenwick (BIT) Tree para sinal do produto dos elementos.
3 | *
4 | * Os pares do vetor ft armazenam, respectivamente, o número de zeros e o
5 | * sinal do produto no intervalo correspondente ao índice i.
6 | *
7 | * Para modificar o valor do elemento na posição i, é preciso primeiro
8 | * apagar o elemento (método erase()) para depois chamar o update().
9 | *
10 | * Autor: Edson Alves
11 | * Data: 07/09/2015
12 | * Licença: LGPL. Sem copyright.
13 | */
14 | #ifndef PRODUCT_FENWICK_TREE_H
15 | #define PRODUCT_FENWICK_TREE_H
16 |
17 | #include
18 |
19 | using namespace std;
20 |
21 | #define LSB(n) ((n) & (-n))
22 |
23 | class ProductFenwickTree
24 | {
25 | private:
26 | int m_N;
27 | vector< pair > ft;
28 | vector ns;
29 |
30 | public:
31 | ProductFenwickTree(int N)
32 | : m_N(N)
33 | {
34 | ft.assign(N + 1, make_pair(0, 1));
35 | ns.assign(N + 1, 1);
36 | }
37 |
38 | int RPQ(int a, int b)
39 | {
40 | auto A = (a == 1) ? make_pair(0, 1) : RPQ(a - 1);
41 | auto B = RPQ(b);
42 |
43 | return (B.first > A.first) ? 0 : B.second * A.second;
44 | }
45 |
46 | void erase(int i)
47 | {
48 | int n = i;
49 |
50 | while (n <= m_N)
51 | {
52 | switch (ns[i]) {
53 | case 0:
54 | --ft[n].first;
55 | break;
56 |
57 | case -1:
58 | ft[n].second *= -1;
59 | break;
60 | }
61 |
62 | n += LSB(n);
63 | }
64 |
65 | ns[i] = 1;
66 | }
67 |
68 | void update(int i, int v)
69 | {
70 | int n = i;
71 |
72 | while (n <= m_N)
73 | {
74 | switch (v) {
75 | case 0:
76 | ++ft[n].first;
77 | break;
78 |
79 | case -1:
80 | ft[n].second *= -1;
81 | break;
82 | }
83 |
84 | n += LSB(n);
85 | }
86 |
87 | ns[i] = v;
88 | }
89 |
90 | private:
91 |
92 | pair RPQ(int b)
93 | {
94 | auto p = make_pair(0, 1);
95 |
96 | while (b)
97 | {
98 | p.first += ft[b].first;
99 | p.second *= ft[b].second;
100 | b -= LSB(b);
101 | }
102 |
103 | return p;
104 | }
105 | };
106 |
107 | #endif
108 |
--------------------------------------------------------------------------------
/algorithms/data_structures/segment_tree.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que representa uma árvore de segmentos.
3 | *
4 | * Suporta range queries e point updates, com implementação recursiva.
5 | *
6 | * Autor: Edson Alves
7 | * Data: 06/05/2018
8 | * Licença: LGPL. Sem copyright.
9 | */
10 | #ifndef SEGMENT_TREE_H
11 | #define SEGMENT_TREE_H
12 |
13 | using std::vector;
14 |
15 |
16 | template
17 | class SegmentTree
18 | {
19 | int n;
20 | vector tree;
21 |
22 | public:
23 | SegmentTree(int N)
24 | : n(N), tree(4*n, 0) // 4N is a upper bound to the number of nodes
25 | {
26 | }
27 |
28 | T sum(int i, int j)
29 | {
30 | return sum(1, 0, n - 1, i, j);
31 | }
32 |
33 | void add(int i, T value)
34 | {
35 | add(1, 0, n - 1, i, value);
36 | }
37 |
38 | int size() const
39 | {
40 | return tree.size();
41 | }
42 |
43 | private:
44 |
45 | int left(int p)
46 | {
47 | return 2 * p;
48 | }
49 |
50 | int right(int p)
51 | {
52 | return 2 * p + 1;
53 | }
54 |
55 | T sum(int p, int L, int R, int i, int j)
56 | {
57 | if (i > R or j < L) // [i, j] don't intersect [L, R]
58 | return 0;
59 |
60 | if (i <= L and R <= j) // [i, j] contain [L, R]
61 | return tree[p];
62 |
63 | T a = sum(left(p), L, (L + R)/2, i, j);
64 | T b = sum(right(p), (L + R)/2 + 1, R, i, j);
65 |
66 | return a + b;
67 | }
68 |
69 | void add(int p, int L, int R, int a, T value)
70 | {
71 | if (a > R or a < L) // Base case: a is not int [L, R]
72 | return;
73 |
74 | tree[p] += value;
75 |
76 | if (L == R) // Base case: we reached a leaf
77 | return;
78 |
79 | add(left(p), L, (L+R)/2, a, value);
80 | add(right(p), (L+R)/2 + 1, R, a, value);
81 | }
82 | };
83 |
84 | #endif
85 |
--------------------------------------------------------------------------------
/algorithms/data_structures/segment_tree_bottom_up.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que representa uma árvore de segmentos.
3 | *
4 | * Esta versão suporta range queries e point updates e não usa recursão. Baseada no exemplo
5 | * dado no livro Competitive Programmers Handbook's, pg. 89.
6 | *
7 | * Autor: Edson Alves
8 | * Data: 04/05/2017
9 | * Licença: LGPL. Sem copyright.
10 | */
11 | #ifndef SEGMENT_TREE_H
12 | #define SEGMENT_TREE_H
13 |
14 | #include
15 |
16 | using std::vector;
17 |
18 |
19 | template
20 | class SegmentTree
21 | {
22 | int n;
23 | vector tree;
24 |
25 | public:
26 | SegmentTree(int N)
27 | : n(least_power_of_2_greater_or_equals(N)), tree(2*n, 0)
28 | {
29 | }
30 |
31 | void add(int i, T v) // Adds v to position i
32 | {
33 | int a = i + n;
34 |
35 | tree[a] += v; // Update the leaf
36 |
37 | while (a >>= 1)
38 | tree[a] = tree[2*a] + tree[2*a + 1]; // Update its parents
39 | }
40 |
41 | T sum(int i, int j)
42 | {
43 | int a = i + n, b = j + n; // The leaves are in second half of tree array
44 | T s = 0;
45 |
46 | while (a <= b)
47 | {
48 | if (a & 1) // a is a right child and must be added to the total
49 | s += tree[a++];
50 |
51 | if (not (b & 1)) // b is a left child and must be added to the total
52 | s += tree[b--];
53 |
54 | // If a is a left child of b is a right child the parent node covers them
55 |
56 | // Move up one level
57 | a /= 2;
58 | b /= 2;
59 | }
60 |
61 | return s;
62 | }
63 |
64 | int size() const
65 | {
66 | return n;
67 | }
68 | };
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/algorithms/data_structures/segment_tree_with_lazy_propagation.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que representa uma árvore de segmentos.
3 | *
4 | * Esta versão suporta range updates com lazy propagation.
5 | *
6 | * Autor: Edson Alves
7 | * Data: 30/09/2015
8 | * Licença: LGPL. Sem copyright.
9 | */
10 | #ifndef SEGMENT_TREE_H
11 | #define SEGMENT_TREE_H
12 |
13 | #include
14 |
15 | using namespace std;
16 | using std::vector;
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | template
23 | class SegmentTree
24 | {
25 | int n;
26 | vector tree, lazy;
27 |
28 | public:
29 | SegmentTree(int N)
30 | : n(N), tree(4*n, 0), lazy(4*n, 0) // 4N is a upper bound to the number of nodes
31 | {
32 | }
33 |
34 | T sum(int i, int j)
35 | {
36 | return sum(1, 0, n - 1, i, j);
37 | }
38 |
39 | void add(int i, int j, T v)
40 | {
41 | add(1, 0, n - 1, i, j, v);
42 | }
43 |
44 | private:
45 |
46 | int left(int p)
47 | {
48 | return 2 * p;
49 | }
50 |
51 | int right(int p)
52 | {
53 | return 2 * p + 1;
54 | }
55 |
56 | T sum(int p, int L, int R, int a, int b)
57 | {
58 | // Lazy propagation
59 | if (lazy[p])
60 | {
61 | tree[p] += (R - L + 1) * lazy[p];
62 |
63 | if (L < R) // If its not a leaf and not zero, propagates
64 | {
65 | lazy[left(p)] += lazy[p];
66 | lazy[right(p)] += lazy[p];
67 | }
68 |
69 | lazy[p] = 0;
70 | }
71 |
72 | if (a > R or b < L) // Base case: [a, b] intersection [L, R] is empty
73 | return 0;
74 |
75 | if (a <= L and R <= b) // Base case: [a, b] contain [L, R]
76 | return tree[p];
77 |
78 | T x = sum(left(p), L, (L + R)/2, a, b);
79 | T y = sum(right(p), (L + R)/2 + 1, R, a, b);
80 |
81 | return x + y;
82 | }
83 |
84 | void add(int p, int L, int R, int a, int b, T value)
85 | {
86 | // Lazy propagation
87 | if (lazy[p])
88 | {
89 | tree[p] += (R - L + 1) * lazy[p];
90 |
91 | if (L < R) // If its not a leaf and not zero, propagates
92 | {
93 | lazy[left(p)] += lazy[p];
94 | lazy[right(p)] += lazy[p];
95 | }
96 |
97 | lazy[p] = 0;
98 | }
99 |
100 | if (a > R or b < L) // Base case: [a, b] intersection [L, R] is empty
101 | return;
102 |
103 | if (a <= L and R <= b) // Base case: [a, b] contain [L, R]
104 | {
105 | tree[p] += (R - L + 1) * value;
106 |
107 | if (L < R) // If its not a leaf and not zero, propagates
108 | {
109 | lazy[left(p)] += value;
110 | lazy[right(p)] += value;
111 | }
112 |
113 | return;
114 | }
115 |
116 | add(left(p), L, (L + R)/2, a, b, value);
117 | add(right(p), (L + R)/2 + 1, R, a, b, value);
118 |
119 | tree[p] = tree[left(p)] + tree[right(p)];
120 | }
121 |
122 | public:
123 | void print() const
124 | {
125 | queue> q;
126 |
127 | q.emplace(1, 0, n - 1, tree[1], lazy[1]);
128 |
129 | while (not q.empty())
130 | {
131 | int p, a, b, v, L;
132 |
133 | tie(p, a, b, v, L) = q.front();
134 | q.pop();
135 |
136 | cout << "[" << a << ", " << b << "] = " << v << ", lazy = " << L << '\n';
137 |
138 | if (a < b)
139 | {
140 | q.emplace(2*p, a, (a + b)/2, tree[2*p], lazy[2*p]);
141 | q.emplace(2*p + 1, (a + b)/2 + 1, b, tree[2*p + 1], lazy[2*p + 1]);
142 | }
143 | }
144 | }
145 | };
146 |
147 | #endif
148 |
--------------------------------------------------------------------------------
/algorithms/data_structures/union_find.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe UDFS (Union-Find Disjoint Sets)
3 | *
4 | * Autor: Edson Alves
5 | * Data: 31/08/2015
6 | * Licença: LGPL. Sem copyright.
7 | */
8 | #ifndef UNION_FIND_H
9 | #define UNION_FIND_H
10 |
11 | #define UDFS_MAX_N 1000005
12 |
13 | int parent[UDFS_MAX_N];
14 | int rank[UDFS_MAX_N];
15 |
16 | class UnionFind
17 | {
18 | public:
19 | UnionFind(int N)
20 | : m_N(N), m_count(N)
21 | {
22 | for (int i = 1; i <= N; ++i)
23 | {
24 | parent[i] = i;
25 | rank[i] = 0;
26 | }
27 | }
28 |
29 | bool is_same_set(int i, int j)
30 | {
31 | return find_set(i) == find_set(j);
32 | }
33 |
34 | void union_set(int i, int j)
35 | {
36 | if (is_same_set(i, j))
37 | return;
38 |
39 | int p = find_set(i);
40 | int q = find_set(j);
41 |
42 | if (rank[p] > rank[q])
43 | parent[q] = p;
44 | else if (rank[q] > rank[p])
45 | parent[p] = q;
46 | else
47 | {
48 | parent[q] = p;
49 | ++rank[p];
50 | }
51 |
52 | --m_count;
53 | }
54 |
55 | int count() const { return m_count; }
56 |
57 | int find_set(int i)
58 | {
59 | int p = i;
60 |
61 | vector ps;
62 |
63 | while (p != parent[p])
64 | {
65 | ps.push_back(p);
66 | p = parent[p];
67 | }
68 |
69 | for (auto x : ps)
70 | {
71 | parent[x] = p;
72 | }
73 |
74 | return p;
75 | }
76 |
77 | private:
78 | int m_N;
79 | int m_count;
80 | };
81 |
82 | #endif
83 |
--------------------------------------------------------------------------------
/algorithms/dp/lis.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que contém algoritmos para o problema LIS (longest increasing
3 | * subsequence).
4 | *
5 | * Autor: Edson Alves
6 | * Data: 01/10/2015
7 | * Licença: LGPL. Sem copyright.
8 | */
9 | #ifndef LIS_H
10 | #define LIS_H
11 |
12 | #include
13 | #include
14 | #include
15 |
16 | #define LIS_MAX_N 1000010
17 |
18 | int lis[LIS_MAX_N], index[LIS_MAX_N], parent[LIS_MAX_N];
19 |
20 | using std::vector;
21 | using std::max;
22 | using std::lower_bound;
23 |
24 | class LIS
25 | {
26 | public:
27 |
28 | /* O algoritmo DP tem por estado LIS(i), que contém o tamanho da maior
29 | * subsequencia crescente que termina no índice i do array base.
30 | * Cada etapa tenha estender as sequências anteriores, escolhendo a
31 | * maior delas possível.
32 | *
33 | * Complexidade: O(n^2)
34 | */
35 | static int dp(const vector& v)
36 | {
37 | size_t N = v.size();
38 | int max_len = 0;
39 |
40 | for (size_t i = 0; i < N; ++i)
41 | {
42 | lis[i] = 1;
43 |
44 | for (size_t j = 0; j < i; ++j)
45 | {
46 | if (v[i] >= v[j])
47 | lis[i] = max(lis[j] + 1, lis[i]);
48 | }
49 |
50 | max_len = max(lis[i], max_len);
51 | }
52 |
53 | return max_len;
54 | }
55 |
56 | /* A solução gulosa com D&C mantém um vetor ordenado (lis) que contém
57 | * o menor elemento que encerra uma subsequência de comprimento i, e
58 | * procurar pelo maior elemento menor do que A[i] para tentar ampliar
59 | * ou melhorar a sequência lis.
60 | *
61 | * Complexidade: O(n log k), k - comprimento de lis
62 | */
63 | static int greedy(const vector& A)
64 | {
65 | lis[0] = A[0];
66 | index[0] = 0;
67 | parent[0] = 0;
68 | int k = 1;
69 |
70 | for (size_t i = 1; i < A.size(); ++i)
71 | {
72 | parent[i] = i;
73 |
74 | auto it = lower_bound(lis, lis + k, A[i]);
75 |
76 | if (it == lis + k)
77 | {
78 | parent[i] = index[k - 1];
79 | lis[k] = A[i];
80 | index[k++] = i;
81 | } else
82 | {
83 | int pos = it - lis;
84 |
85 | if (lis[pos] > A[i])
86 | {
87 | lis[pos] = A[i];
88 | index[pos] = i;
89 |
90 | if (pos > 0)
91 | parent[i] = index[pos - 1];
92 | }
93 | }
94 | }
95 |
96 | return k;
97 | }
98 | };
99 |
100 | #endif
101 |
--------------------------------------------------------------------------------
/algorithms/dp/main_lis.cpp:
--------------------------------------------------------------------------------
1 | #include "lis.h"
2 |
3 | using namespace std;
4 |
5 | int main()
6 | {
7 | vector A { -7, 10, 9, 2, 3, 8, 8, 1, 2, 3, 4 };
8 |
9 | cout << LIS::greedy(A) << endl;
10 |
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------
/algorithms/dp/max1Drangesum.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que contém algoritmos para o problema max 1D range sum.
3 | *
4 | * Autor: Edson Alves
5 | * Data: 28/09/2015
6 | * Licença: LGPL. Sem copyright.
7 | */
8 | #ifndef MAX_1D_RANGE_SUM_H
9 | #define MAX_1D_RANGE_SUM_H
10 |
11 | #include
12 |
13 | using std::vector;
14 |
15 | class Max1DRangeSum
16 | {
17 | public:
18 |
19 | /* O algoritmo de Kadane tenta ampliar a soma de forma gulosa, resetando-a
20 | * caso se torne negativa (melhor reiniciar de zero do que partir de uma
21 | * quantia negativa). Equivale a uma DP de um parâmetro como redução de
22 | * memória.
23 | *
24 | * Complexidade: O(n)
25 | */
26 | static int kadane(const vector& v)
27 | {
28 | int sum = 0, max_sum = 0;
29 |
30 | for (auto n : v)
31 | {
32 | sum += n;
33 | max_sum = max(sum, max_sum);
34 |
35 | if (sum < 0) sum = 0;
36 | }
37 |
38 | return max_sum;
39 | }
40 |
41 | /* Algoritmo DP para o problema. É mais lento do que o algoritmo de
42 | * Kadane, porém é mais geral e adaptável. Pré-computa as somas acumuladas
43 | * e depois testa todos os pares de índices possíveis em busca da
44 | * maior soma.
45 | *
46 | * Complexidade: O(n^2)
47 | */
48 | static int dp(const vector& v)
49 | {
50 | // Caso trivial
51 | if (v.size() == 0)
52 | return 0;
53 |
54 | // Pré-computa as somas acumuladas
55 | vector& a { v[0] };
56 |
57 | for (size_t i = 1; i < v.size(); ++i)
58 | a[i] += a[i - 1];
59 |
60 | /* Testa todos os pares possíveis:
61 | * Soma[0, j] = a[j]
62 | * Soma[i, j] = a[j] - a[i - j], i != 0
63 | */
64 | int max_sum = 0;
65 |
66 | for (size_t i = 0; i < v.size(): ++i)
67 | for (size_t j = i; j < v.size(); ++j)
68 | {
69 | if (i == 0)
70 | max_sum = max(a[j], max_sum);
71 | else
72 | max_sum = max(a[j] - a[i - 1], max_sum);
73 | }
74 |
75 | return max_sum;
76 | }
77 | };
78 |
79 | #endif
80 |
--------------------------------------------------------------------------------
/algorithms/dp/max2Drangesum.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que contém algoritmos para o problema max 2D range sum.
3 | *
4 | * Os pontos P e Q representam o canto superior esquerdo e o ponto inferior
5 | * direito do retângulo, respectivamente.
6 | *
7 | * Autor: Edson Alves
8 | * Data: 28/09/2015
9 | * Licença: LGPL. Sem copyright.
10 | */
11 | #ifndef MAX_2D_RANGE_SUM_H
12 | #define MAX_2D_RANGE_SUM_H
13 |
14 | #include
15 | #include
16 |
17 | using std::vector;
18 | using std::max;
19 |
20 | #define MAX_N 110
21 |
22 | class Max2DRangeSum
23 | {
24 | public:
25 |
26 | /* Algoritmo de Busca Completa para o problema. Lento, mas correto.
27 | *
28 | * Complexidade: O(n^6)
29 | */
30 | static int cs(const int A[][MAX_N], int m, int n)
31 | {
32 | int max_sum = -(1 << 30);
33 |
34 | // Escolhe a região retangular
35 | for (int px = 0; px < m; ++px)
36 | for (int py = 0; py < n; ++py)
37 | for (int qx = px; qx < m; ++qx)
38 | for (int qy = py; qy < n; ++qy)
39 | {
40 | int sum = 0;
41 |
42 | // Computa a soma da região retangular
43 | for (int i = px; i <= qx; ++i)
44 | for (int j = py; j <= qy; ++j)
45 | sum += A[i][j];
46 |
47 | max_sum = max(sum, max_sum);
48 | }
49 |
50 | return max_sum;
51 | }
52 |
53 | /* Algoritmo DP para o problema. Pré-computa as somas acumuladas
54 | * e depois testa todos os pares de índices possíveis em busca da
55 | * maior soma. Evita a soma de um termo múltiplas vezes utilizando o
56 | * princípio a inclusão-exclusão.
57 | *
58 | * Obs.: o algoritmo irá modificar a matriz de entrada para guardar as
59 | * somas acumuladas.
60 | *
61 | * Complexidade: O(n^4)
62 | */
63 | static int dp(int A[][MAX_N], int m, int n)
64 | {
65 | // Pré-computa as somas acumuladas
66 | for (int i = 0; i < m; ++i)
67 | for (int j = 0; j < n; ++j)
68 | {
69 | if (i > 0) A[i][j] += A[i - 1][j];
70 | if (j > 0) A[i][j] += A[i][j - 1];
71 | if (i > 0 and j > 0) A[i][j] -= A[i - 1][j - 1];
72 | }
73 |
74 | // Testa todos os pares possíveis:
75 | int max_sum = -(1 << 30);
76 |
77 | for (int px = 0; px < m; ++px)
78 | for (int py = 0; py < n; ++py)
79 | for (int qx = px; qx < m; ++qx)
80 | for (int qy = py; qy < n; ++qy)
81 | {
82 | int sum = A[qx][qy];
83 |
84 | if (px > 0) sum -= A[px - 1][qy];
85 | if (py > 0) sum -= A[qx][py - 1];
86 | if (px > 0 and py > 0) sum += A[px - 1][py - 1];
87 |
88 | max_sum = max(sum, max_sum);
89 | }
90 |
91 | return max_sum;
92 | }
93 | };
94 |
95 | #endif
96 |
--------------------------------------------------------------------------------
/algorithms/dp/max3Drangesum.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | #define MAX 22
6 |
7 | long long M[MAX][MAX][MAX];
8 |
9 | int main()
10 | {
11 | int T;
12 | scanf("%d", &T);
13 |
14 | for (int test = 0; test < T; ++test)
15 | {
16 | int A, B, C;
17 | scanf("%d %d %d", &A, &B, &C);
18 |
19 | for (int x = 0; x < A; ++x)
20 | for (int y = 0; y < B; ++y)
21 | for (int z = 0; z < C; ++z)
22 | {
23 | scanf("%lld", &M[x][y][z]);
24 |
25 | if (x > 0) M[x][y][z] += M[x - 1][y][z];
26 | if (y > 0) M[x][y][z] += M[x][y - 1][z];
27 | if (z > 0) M[x][y][z] += M[x][y][z - 1];
28 |
29 | if (x > 0 and y > 0) M[x][y][z] -= M[x - 1][y - 1][z];
30 | if (x > 0 and z > 0) M[x][y][z] -= M[x - 1][y][z - 1];
31 | if (y > 0 and y > 0) M[x][y][z] -= M[x][y - 1][z - 1];
32 |
33 | if (x > 0 and y > 0 and z > 0) M[x][y][z] += M[x-1][y-1][z-1];
34 | }
35 |
36 | long long max_sum = -(1LL << 60);
37 |
38 | for (int x = 0; x < A; ++x)
39 | for (int y = 0; y < B; ++y)
40 | for (int z = 0; z < C; ++z)
41 | for (int a = x; a < A; ++a)
42 | for (int b = y; b < B; ++b)
43 | for (int c = z; c < C; ++c)
44 | {
45 | long long sum = M[a][b][c];
46 |
47 | if (x > 0) sum -= M[x - 1][b][c];
48 | if (y > 0) sum -= M[a][y - 1][c];
49 | if (z > 0) sum -= M[a][b][z - 1];
50 |
51 | if (x > 0 and y > 0) sum += M[x - 1][y - 1][c];
52 | if (x > 0 and z > 0) sum += M[x - 1][b][z - 1];
53 | if (y > 0 and y > 0) sum += M[a][y - 1][z - 1];
54 |
55 | if (x > 0 and y > 0 and z > 0) sum -= M[x-1][y-1][z-1];
56 |
57 | max_sum = max(sum, max_sum);
58 | }
59 |
60 | if (test) printf("\n");
61 |
62 | printf("%lld\n", max_sum);
63 | }
64 |
65 | return 0;
66 | }
67 |
--------------------------------------------------------------------------------
/algorithms/geometry/circle.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que representa um círculo no espaço bidimensional
3 | *
4 | * Autor: Edson Alves
5 | * Data: 18/07/2016
6 | * Licença: LGPL. Sem copyright.
7 | */
8 | #ifndef GEOMETRY_CIRCLE_H
9 | #define GEOMETRY_CIRCLE_H
10 |
11 | #include
12 |
13 | #include "point.h"
14 |
15 | class Circle {
16 | public:
17 | Point C;
18 | double r;
19 |
20 | typedef enum { IN, OUT, ON } PointPosition;
21 |
22 | Circle(const Point& Cv = Point(0.0, 0.0), double rv = 1.0) : C(Cv), r(rv) {}
23 |
24 | bool operator==(const Circle& c) const
25 | {
26 | return C == c.C and equals(r, c.r);
27 | }
28 |
29 | bool operator!=(const Circle& c) const
30 | {
31 | return not (*this == c);
32 | }
33 |
34 | PointPosition position(const Point& P) const
35 | {
36 | auto d = P.distance(C);
37 |
38 | return equals(d, r) ? ON : (d < r ? IN : OUT);
39 | }
40 |
41 | double perimeter() const
42 | {
43 | return 2.0 * M_PI * r;
44 | }
45 |
46 | double area() const
47 | {
48 | return M_PI * r * r;
49 | }
50 |
51 | double arc(double a) const
52 | {
53 | return (a / (2*M_PI)) * perimeter();
54 | }
55 |
56 | double chord(double a) const
57 | {
58 | return 2 * r * sin(a/2);
59 | }
60 |
61 | double sector(double a) const
62 | {
63 | return (a / (2*M_PI)) * area();
64 | }
65 |
66 | double segment(double a) const
67 | {
68 | auto c = chord(a);
69 | auto s = (r + r + c)/2.0; // Semiperímetro
70 | auto T = sqrt(s*(s - r)*(s - r)*(s - c)); // Área do triângulo
71 |
72 | return sector(a) - T;
73 | }
74 |
75 | static std::vector
76 | from_2_points_and_radius(const Point& P, const Point& Q, double r)
77 | {
78 | std::vector cs;
79 |
80 | if (P == Q)
81 | {
82 | cs.push_back(Circle(P.translate(r, 0), r));
83 | cs.push_back(Circle(P.translate(0, r), r));
84 | cs.push_back(Circle(P.translate(-r, 0), r));
85 | cs.push_back(Circle(P.translate(0, -r), r));
86 |
87 | return cs;
88 | }
89 |
90 | double d2 = (P.x - Q.x) * (P.x - Q.x) + (P.y - Q.y) * (P.y - Q.y);
91 | double det = r * r / d2 - 0.25;
92 |
93 | if (det < 0.0)
94 | return cs;
95 |
96 | double h = sqrt(det);
97 |
98 | auto x = (P.x + Q.x) * 0.5 + (P.y - Q.y) * h;
99 | auto y = (P.y + Q.y) * 0.5 + (Q.x - P.x) * h;
100 |
101 | cs.push_back(Circle(Point(x, y), r));
102 |
103 | x = (Q.x + P.x) * 0.5 + (Q.y - P.y) * h;
104 | y = (Q.y + P.y) * 0.5 + (P.x - Q.x) * h;
105 |
106 | cs.push_back(Circle(Point(x, y), r));
107 |
108 | return cs;
109 | }
110 |
111 | static std::vector
112 | from_3_points(const Point& P, const Point& Q, const Point& R)
113 | {
114 | std::vector cs;
115 |
116 | auto a = 2*(Q.x - P.x);
117 | auto b = 2*(Q.y - P.y);
118 | auto c = 2*(R.x - P.x);
119 | auto d = 2*(R.y - P.y);
120 |
121 | auto det = a*d - b*c;
122 |
123 | // Colinear points
124 | if (equals(det, 0))
125 | return cs;
126 |
127 | auto k1 = (Q.x*Q.x + Q.y*Q.y) - (P.x*P.x + P.y*P.y);
128 | auto k2 = (R.x*R.x + R.y*R.y) - (P.x*P.x + P.y*P.y);
129 |
130 | auto cx = (k1*d - k2*b)/det;
131 | auto cy = (a*k2 - c*k1)/det;
132 |
133 | Point C(cx, cy);
134 | auto r = C.distance(P);
135 |
136 | cs.push_back(Circle(C, r));
137 |
138 | return cs;
139 | }
140 | };
141 |
142 | #endif
143 |
--------------------------------------------------------------------------------
/algorithms/geometry/line.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que representa retas no espaço bidimensional
3 | *
4 | * Autor: Edson Alves
5 | * Data: 19/07/2016
6 | * Licença: LGPL. Sem copyright.
7 | */
8 | #ifndef GEOMETRY_LINE_H
9 | #define GEOMETRY_LINE_H
10 |
11 | #include "point.h"
12 |
13 | #include
14 |
15 | using std::pair;
16 |
17 | class Line {
18 | void normalize()
19 | {
20 | auto k = a ? a : b;
21 |
22 | a /= k;
23 | b /= k;
24 | c /= k;
25 | }
26 |
27 | public:
28 | double a;
29 | double b;
30 | double c;
31 |
32 | typedef enum { ZERO, ONE, INF } Intersections;
33 |
34 | Line(double av, double bv, double cv) : a(av), b(bv), c(cv) { normalize(); }
35 |
36 | Line(const Point& P, const Point& Q)
37 | {
38 | a = P.y - Q.y;
39 | b = Q.x - P.x;
40 | c = P.x * Q.y - P.y * Q.x;
41 |
42 | normalize();
43 | }
44 |
45 | bool operator==(const Line& r) const
46 | {
47 | return equals(a, r.a) and equals(b, r.b) and equals(c, r.c);
48 | }
49 |
50 | bool operator!=(const Line& r) const
51 | {
52 | return not (*this == r);
53 | }
54 |
55 | bool parallel(const Line& r) const
56 | {
57 | return equals(a * r.b - b * r.a, 0) and not equals(c, r.c);
58 | }
59 |
60 | bool concurrent(const Line& r) const
61 | {
62 | return not equals(a * r.b - b * r.a, 0);
63 | }
64 |
65 | pair intersections(const Line& r)
66 | {
67 | auto det = a * r.b - b * r.a;
68 |
69 | if (equals(det, 0))
70 | {
71 | // Coincidentes
72 | if (*this == r)
73 | return pair(INF, Point());
74 | else
75 | return pair(ZERO, Point()); // Paralelas
76 | } else // Concorrentes
77 | {
78 | double x = (-c * r.b + r.c * b) / det;
79 | double y = (-r.c * a + c * r.a) / det;
80 |
81 | return pair(ONE, Point(x, y));
82 | }
83 | }
84 | };
85 |
86 | #endif
87 |
--------------------------------------------------------------------------------
/algorithms/geometry/point.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que representa pontos no espaço bidimensional
3 | *
4 | * Autor: Edson Alves
5 | * Data: 18/07/2016
6 | * Licença: LGPL. Sem copyright.
7 | */
8 | #ifndef GEOMEdoubleRY_POINdouble_H
9 | #define GEOMEdoubleRY_POINdouble_H
10 |
11 | #include
12 |
13 | bool equals(double a, double b)
14 | {
15 | static const auto EPS = 1e-9;
16 | return fabs(a - b) < EPS;
17 | }
18 |
19 | class Point {
20 | public:
21 | double x, y;
22 |
23 | Point(double xv = 0, double yv = 0) : x(xv), y(yv) {}
24 |
25 | bool operator==(const Point& P) const
26 | {
27 | return equals(x, P.x) and equals(y, P.y);
28 | }
29 |
30 | bool operator!=(const Point& P) const
31 | {
32 | return not (*this == P);
33 | }
34 |
35 | bool operator<(const Point& P) const
36 | {
37 | return equals(x, P.x) ? y < P.y : x < P.x;
38 | }
39 |
40 | double distance(const Point& P) const
41 | {
42 | return hypot(x - P.x, y - P.y);
43 | }
44 |
45 | Point rotate(double angle)
46 | {
47 | auto px = cos(angle) * x - sin(angle) * y;
48 | auto py = sin(angle) * x + cos(angle) * y;
49 |
50 | return Point { double(px), double(py) };
51 | }
52 |
53 | Point translate(double dx, double dy) const
54 | {
55 | return Point(x + dx, y + dy);
56 | }
57 |
58 | Point scale(double kx, double ky) const
59 | {
60 | return Point(kx*x, ky*y);
61 | }
62 |
63 | Point scale(double k) const
64 | {
65 | return scale(k, k);
66 | }
67 | };
68 |
69 | #endif
70 |
--------------------------------------------------------------------------------
/algorithms/geometry/triangle.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Classe que representa um triângulo no espaço bidimensional
3 | *
4 | * Autor: Edson Alves
5 | * Data: 30/07/2016
6 | * Licença: LGPL. Sem copyright.
7 | */
8 | #ifndef GEOMETRY_TRIANGLE_H
9 | #define GEOMETRY_TRIANGLE_H
10 |
11 | #include "point.h"
12 |
13 | class Triangle {
14 | public:
15 | Point A, B, C;
16 | double a, b, c;
17 |
18 | Triangle(const Point& P, const Point& Q, const Point& R) : A(P), B(Q), C(R)
19 | {
20 | a = P.distance(Q);
21 | b = Q.distance(R);
22 | c = R.distance(P);
23 | }
24 |
25 | Triangle(double av, double bv, double cv) :
26 | A(), B(), C(), a(av), b(bv), c(cv) {}
27 |
28 | typedef enum { EQUILATERAL, ISOSCELES, SCALENE } Sides;
29 |
30 | Sides classification_by_sides() const
31 | {
32 | if (a == b and b == c)
33 | return EQUILATERAL;
34 |
35 | if (a == b or a == c or b == c)
36 | return ISOSCELES;
37 |
38 | return SCALENE;
39 | }
40 |
41 | typedef enum { RIGHT, ACUTE, OBTUSE } Angles;
42 |
43 | Angles classification_by_angles() const
44 | {
45 | auto AB = acos((c*c - a*a - b*b)/(2*a*b));
46 | auto AC = acos((b*b - a*a - c*c)/(2*a*c));
47 | auto BC = acos((a*a - b*b - c*c)/(2*b*c));
48 |
49 | auto right = PI / 2.0;
50 |
51 | if (equals(AB, right) or equals(AC, right) or equals(BC, right))
52 | return RIGHT;
53 |
54 | if (AB > right or AC > right or BC > right)
55 | return OBTUSE;
56 |
57 | return ACUTE;
58 | }
59 |
60 | double perimeter() const
61 | {
62 | return a + b + c;
63 | }
64 |
65 | double area() const
66 | {
67 | auto s = perimetro() / 2.0;
68 |
69 | return sqrt(s*(s - a)*(s - b)*(s - c));
70 | }
71 |
72 | double area2() const
73 | {
74 | double det = (A.x*B.y + A.y*C.x + B.x*C.y) - (C.x*B.y + C.y*A.x + B.x*A.y);
75 |
76 | return 0.5 * fabs(det);
77 | }
78 |
79 | Point barycenter() const
80 | {
81 | auto x = (A.x + B.x + C.x) / 3.0;
82 | auto y = (A.y + B.y + C.y) / 3.0;
83 |
84 | return Point(x, y);
85 | }
86 |
87 | double inradius() const
88 | {
89 | return (2 * area()) / perimeter();
90 | }
91 |
92 | // Centro do círculo inscrito
93 | Point incenter() const
94 | {
95 | auto p = perimeter();
96 | auto x = (a*A.x + b*B.x + c.C.x)/p;
97 | auto y = (a*A.y + b*B.y + c.C.y)/p;
98 |
99 | return Point(x, y);
100 | }
101 |
102 | double circumradius() const
103 | {
104 | return (a * b * c)/(4 * area());
105 | }
106 |
107 | Point circumcenter() const
108 | {
109 | auto d = 2*(A.x*(B.y - C.y) + B.x*(C.y - A.y) + C.x*(A.y - B.y));
110 |
111 | auto A2 = A.x*A.x + A.y*A.y;
112 | auto B2 = B.x*B.x + B.y*B.y;
113 | auto C2 = C.x*C.x + C.y*C.y;
114 |
115 | auto x = (A2*(B.y - C.y) + B2*(C.y - A.y) + C2*(A.y - B.y))/d;
116 | auto y = (A2*(C.x - B.x) + B2*(A.x - C.x) + C2*(B.x - A.x))/d;
117 |
118 | return Point(x, y);
119 | }
120 | };
121 |
122 |
123 | #endif
124 |
125 |
--------------------------------------------------------------------------------
/algorithms/graph/247.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include