├── .gitignore
├── LICENSE
├── README.md
├── data_structures
├── bit.cpp
├── bit2d.cpp
├── bit_build.cpp
├── euler_tour_tree.cpp
├── li_chao.cpp
├── meldable_heap.cpp
├── merge_sort_tree.cpp
├── merge_sort_tree_upd.cpp
├── minqueue.cpp
├── minqueue_sum.cpp
├── mo.cpp
├── mo_hilbert.cpp
├── persistent_seg_dinamic.cpp
├── persistent_treap.cpp
├── seg.cpp
├── seg2d.cpp
├── seg_class.cpp
├── seg_iter.cpp
├── sparse_table.cpp
├── splay.cpp
├── sqrttree.cpp
├── treap.cpp
├── treap_build.cpp
├── treap_impl.cpp
├── trie.cpp
├── trie_xor.cpp
├── wavelet.cpp
└── wavelet_static.cpp
├── dynamic_programming
├── divide_and_conquer.cpp
├── knapsack_01.cpp
├── knapsack_bitset.cpp
├── knapsack_bounded.cpp
├── knapsack_unbounded.cpp
├── lcs.cpp
├── lis.cpp
└── subset_sums.cpp
├── etc
├── bitset_extra.cpp
├── compression.cpp
├── fast_input.cpp
└── seed_random.cpp
├── geometry
├── convex_hull.cpp
├── point.cpp
└── rectangle_union.cpp
├── graph
├── bfs.cpp
├── biconnected_component.cpp
├── bridge_articulation.cpp
├── centroid_decomposition.cpp
├── dfs.cpp
├── dijkstra.cpp
├── dinic.cpp
├── eulerian_path.cpp
├── hld.cpp
├── hungarian.cpp
├── kruskal.cpp
├── lca_binary_lifting.cpp
├── maximum_clique.cpp
├── strongly_connected.cpp
└── union_find.cpp
├── math
├── bigint.cpp
├── binary_gcd.cpp
├── binary_perm.cpp
├── brent.cpp
├── carmichael.cpp
├── choose.cpp
├── compute_wheel.cpp
├── determinant.cpp
├── discrete_log.cpp
├── fast_ilog.cpp
├── fast_modcheck.cpp
├── fast_pollard_rho.cpp
├── gcdext.cpp
├── inv.cpp
├── inverse.cpp
├── linear_mobius.cpp
├── linear_phi.cpp
├── linear_sieve.cpp
├── linear_sieve_ext.cpp
├── matrix_expo.cpp
├── phi.cpp
├── pisano.cpp
├── pollard_rho.cpp
├── prime_count.cpp
├── rabin_miller.cpp
├── rabin_miller_bench.cpp
├── segmented_sieve.cpp
├── segmented_sieve_bit.cpp
├── sieve.cpp
└── wheel_factorization.cpp
└── string
├── aho_corasick.cpp
├── hash.cpp
├── manacher.cpp
├── prefix.cpp
└── suffix_array.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore all
2 | *
3 | # Unignore all with extensions
4 | !*.*
5 | # Unignore all dirs
6 | !*/
7 | !LICENSE
8 | *.txt
9 | gen.*
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | CC0 1.0 Universal
2 |
3 | Statement of Purpose
4 |
5 | The laws of most jurisdictions throughout the world automatically confer
6 | exclusive Copyright and Related Rights (defined below) upon the creator and
7 | subsequent owner(s) (each and all, an "owner") of an original work of
8 | authorship and/or a database (each, a "Work").
9 |
10 | Certain owners wish to permanently relinquish those rights to a Work for the
11 | purpose of contributing to a commons of creative, cultural and scientific
12 | works ("Commons") that the public can reliably and without fear of later
13 | claims of infringement build upon, modify, incorporate in other works, reuse
14 | and redistribute as freely as possible in any form whatsoever and for any
15 | purposes, including without limitation commercial purposes. These owners may
16 | contribute to the Commons to promote the ideal of a free culture and the
17 | further production of creative, cultural and scientific works, or to gain
18 | reputation or greater distribution for their Work in part through the use and
19 | efforts of others.
20 |
21 | For these and/or other purposes and motivations, and without any expectation
22 | of additional consideration or compensation, the person associating CC0 with a
23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
25 | and publicly distribute the Work under its terms, with knowledge of his or her
26 | Copyright and Related Rights in the Work and the meaning and intended legal
27 | effect of CC0 on those rights.
28 |
29 | 1. Copyright and Related Rights. A Work made available under CC0 may be
30 | protected by copyright and related or neighboring rights ("Copyright and
31 | Related Rights"). Copyright and Related Rights include, but are not limited
32 | to, the following:
33 |
34 | i. the right to reproduce, adapt, distribute, perform, display, communicate,
35 | and translate a Work;
36 |
37 | ii. moral rights retained by the original author(s) and/or performer(s);
38 |
39 | iii. publicity and privacy rights pertaining to a person's image or likeness
40 | depicted in a Work;
41 |
42 | iv. rights protecting against unfair competition in regards to a Work,
43 | subject to the limitations in paragraph 4(a), below;
44 |
45 | v. rights protecting the extraction, dissemination, use and reuse of data in
46 | a Work;
47 |
48 | vi. database rights (such as those arising under Directive 96/9/EC of the
49 | European Parliament and of the Council of 11 March 1996 on the legal
50 | protection of databases, and under any national implementation thereof,
51 | including any amended or successor version of such directive); and
52 |
53 | vii. other similar, equivalent or corresponding rights throughout the world
54 | based on applicable law or treaty, and any national implementations thereof.
55 |
56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of,
57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
59 | and Related Rights and associated claims and causes of action, whether now
60 | known or unknown (including existing as well as future claims and causes of
61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum
62 | duration provided by applicable law or treaty (including future time
63 | extensions), (iii) in any current or future medium and for any number of
64 | copies, and (iv) for any purpose whatsoever, including without limitation
65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
66 | the Waiver for the benefit of each member of the public at large and to the
67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver
68 | shall not be subject to revocation, rescission, cancellation, termination, or
69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work
70 | by the public as contemplated by Affirmer's express Statement of Purpose.
71 |
72 | 3. Public License Fallback. Should any part of the Waiver for any reason be
73 | judged legally invalid or ineffective under applicable law, then the Waiver
74 | shall be preserved to the maximum extent permitted taking into account
75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
76 | is so judged Affirmer hereby grants to each affected person a royalty-free,
77 | non transferable, non sublicensable, non exclusive, irrevocable and
78 | unconditional license to exercise Affirmer's Copyright and Related Rights in
79 | the Work (i) in all territories worldwide, (ii) for the maximum duration
80 | provided by applicable law or treaty (including future time extensions), (iii)
81 | in any current or future medium and for any number of copies, and (iv) for any
82 | purpose whatsoever, including without limitation commercial, advertising or
83 | promotional purposes (the "License"). The License shall be deemed effective as
84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the
85 | License for any reason be judged legally invalid or ineffective under
86 | applicable law, such partial invalidity or ineffectiveness shall not
87 | invalidate the remainder of the License, and in such case Affirmer hereby
88 | affirms that he or she will not (i) exercise any of his or her remaining
89 | Copyright and Related Rights in the Work or (ii) assert any associated claims
90 | and causes of action with respect to the Work, in either case contrary to
91 | Affirmer's express Statement of Purpose.
92 |
93 | 4. Limitations and Disclaimers.
94 |
95 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
96 | surrendered, licensed or otherwise affected by this document.
97 |
98 | b. Affirmer offers the Work as-is and makes no representations or warranties
99 | of any kind concerning the Work, express, implied, statutory or otherwise,
100 | including without limitation warranties of title, merchantability, fitness
101 | for a particular purpose, non infringement, or the absence of latent or
102 | other defects, accuracy, or the present or absence of errors, whether or not
103 | discoverable, all to the greatest extent permissible under applicable law.
104 |
105 | c. Affirmer disclaims responsibility for clearing rights of other persons
106 | that may apply to the Work or any use thereof, including without limitation
107 | any person's Copyright and Related Rights in the Work. Further, Affirmer
108 | disclaims responsibility for obtaining any necessary consents, permissions
109 | or other rights required for any use of the Work.
110 |
111 | d. Affirmer understands and acknowledges that Creative Commons is not a
112 | party to this document and has no duty or obligation with respect to this
113 | CC0 or use of the Work.
114 |
115 | For more information, please see
116 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # algorithm-implementations
2 | Competitive programming algorithms implementations in C++
3 |
--------------------------------------------------------------------------------
/data_structures/bit.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | // const int maxn = 1010101;
6 |
7 | template
8 | struct bit
9 | {
10 | T v[maxn];
11 |
12 | void add(int x, const T& d)
13 | {
14 | for (int i = x; i < maxn; i += i&-i)
15 | v[i] += d;
16 | }
17 |
18 | T get(int x)
19 | {
20 | T ans{};
21 | for (int i = x; i > 0; i -= i&-i)
22 | ans += v[i];
23 | return ans;
24 | }
25 | };
26 |
27 | bit b;
28 |
29 | int main()
30 | {
31 |
32 | }
--------------------------------------------------------------------------------
/data_structures/bit2d.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | template
6 | struct Bit2d
7 | {
8 | T b[size][size];
9 |
10 | void add(int x, int y, T d)
11 | {
12 | for (int i = x; i < size; i += i&-i) {
13 | for (int j = y; j < size; j += j&-j)
14 | b[i][j] += d;
15 | }
16 | }
17 |
18 | T get(int x, int y)
19 | {
20 | T ans = 0;
21 | for (int i = x; i; i -= i&-i) {
22 | for (int j = y; j; j -= j&-j) {
23 | ans += b[i][j];
24 | }
25 | }
26 | }
27 | };
28 |
29 | int main()
30 | {
31 |
32 | }
--------------------------------------------------------------------------------
/data_structures/bit_build.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | template
6 | struct Bit
7 | {
8 | int b[size];
9 |
10 | void add(int x, int d)
11 | {
12 | for (int i = x; i < size; i += i&-i)
13 | b[i] += d;
14 | }
15 |
16 | int get(int x)
17 | {
18 | int ans = 0;
19 | for (int i = x; i; i -= i&-i)
20 | ans += b[i];
21 | return ans;
22 | }
23 |
24 | void build(int* v, int n)
25 | {
26 | for (int i = 1; i <= n; i++) {
27 | b[i] += v[i];
28 | if (i + (i&-i) < size)
29 | b[i + (i&-i)] += b[i];
30 | }
31 | }
32 |
33 | void linearize(int *v, int n)
34 | {
35 | for (int i = n; i >= 1; i--) {
36 | if (i + (i&-i) < size)
37 | b[i + (i&-i)] -= b[i];
38 | }
39 | for (int i = 1; i <= n; i++ )
40 | v[i] = b[i];
41 | }
42 | };
43 |
44 | const int maxn = 101010;
45 |
46 | int v[maxn];
47 | Bit bit;
48 |
49 | int main()
50 | {
51 | int n;
52 | cin >> n;
53 |
54 | for (int i = 1; i <= n; i++)
55 | cin >> v[i];
56 |
57 | bit.build(v, n);
58 |
59 | int q;
60 | cin >> q;
61 |
62 | while (q--) {
63 | int op;
64 | cin >> op;
65 |
66 | // update
67 | if (op == 1) {
68 | int pos, val;
69 | cin >> pos >> val;
70 |
71 | bit.add(pos, val-v[pos]);
72 | v[pos] = val;
73 | }
74 | // query
75 | else {
76 | int x;
77 | cin >> x;
78 |
79 | cout << bit.get(x) << "\n";
80 | }
81 | }
82 |
83 | bit.linearize(v, n);
84 | for (int i = 1; i <= n; i++)
85 | cout << v[i] << " ";
86 | cout << "\n";
87 | }
--------------------------------------------------------------------------------
/data_structures/euler_tour_tree.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define ff first
4 | #define ss second
5 |
6 | #define pb push_back
7 | #define eb emplace_back
8 | #define all(x) begin(x), end(x)
9 | #define rall(x) rbegin(x), rend(x)
10 | #define clr(x, c) memset((x), (c), sizeof((x)))
11 |
12 | using namespace std;
13 |
14 | template void DBG(T&& x) { cerr << x << " "; }
15 | template void DBG(T&& x, Args&&... args) { DBG(x); DBG(args...); }
16 | #define DBG(...) cerr << "[" << #__VA_ARGS__ << "]: "; DBG(__VA_ARGS__); cerr << endl
17 |
18 |
19 | using ll = long long;
20 | using ii = pair;
21 |
22 | int const inf = 0x3f3f3f3f;
23 | ll const linf = 0x3f3f3f3f3f3f3f3f;
24 |
25 | int const mod = 1e9 + 7;
26 |
27 | seed_seq seq {
28 | (uint64_t) chrono::duration_cast(
29 | chrono::high_resolution_clock::now().
30 | time_since_epoch()).count(),
31 | (uint64_t) __builtin_ia32_rdtsc(),
32 | (uint64_t) random_device{}(),
33 | (uint64_t) 17
34 | };
35 |
36 | mt19937 rd{seq};
37 |
38 | namespace Treap {
39 | struct Node
40 | {
41 | int v;
42 | int h, sz = 1;
43 | ll cheese = 0, sauce = 0;
44 | ll sum_cheese = 0, sum_sauce = 0;
45 | ll lazy_sauce = 0;
46 | Node *l = nullptr, *r = nullptr, *pai = nullptr;
47 |
48 | Node(int x)
49 | : v(x), h(rd()) {};
50 | };
51 |
52 | using treap = Node*;
53 |
54 | int sz(treap t) {
55 | return t? t->sz : 0;
56 | }
57 |
58 | void push(treap t) {
59 | if (!t) return;
60 | t->sauce += t->lazy_sauce;
61 | t->sum_sauce += t->lazy_sauce * sz(t);
62 | if (t->l) t->l->lazy_sauce += t->lazy_sauce;
63 | if (t->r) t->r->lazy_sauce += t->lazy_sauce;
64 | t->lazy_sauce = 0;
65 | }
66 |
67 | void reset(treap t) {
68 | if (!t) return;
69 | t->sum_sauce = t->sauce;
70 | t->sum_cheese = t->cheese;
71 | }
72 |
73 | void op(treap t) {
74 | if (!t) return;
75 | t->sz = 1 + sz(t->l) + sz(t->r);
76 |
77 | reset(t);
78 | push(t->l);
79 | push(t->r);
80 |
81 | if (t->l) {
82 | t->l->pai = t;
83 | t->sum_cheese += t->l->sum_cheese;
84 | t->sum_sauce += t->l->sum_sauce;
85 | }
86 |
87 | if (t->r) {
88 | t->r->pai = t;
89 | t->sum_cheese += t->r->sum_cheese;
90 | t->sum_sauce += t->r->sum_sauce;
91 | }
92 | }
93 |
94 | void merge(treap &t, treap l, treap r) {
95 | push(l), push(r); op(l), op(r);
96 | if (!l or !r)
97 | (t=l?l:r);
98 | else if (l->h > r->h)
99 | merge(l->r, l->r, r), t = l;
100 | else
101 | merge(r->l, l, r->l), t = r;
102 | op(t);
103 | }
104 |
105 | void split(treap t, treap &l, treap &r, int pos) {
106 | push(t); op(t);
107 | if (!t) return void(l=r=nullptr);
108 | int p = sz(t->l) + 1;
109 |
110 | if (pos > p)
111 | split(t->r, t->r, r, pos - p), l = t;
112 | else
113 | split(t->l, l, t->l, pos), r = t;
114 |
115 | op(l), op(r);
116 | }
117 |
118 | int pos(treap t) {
119 | if (!t) return 0;
120 | if (!t->pai) return sz(t->l) + 1;
121 | return (t == t->pai->r? sz(t->l) + 1 : -sz(t->r)-1) + pos(t->pai);
122 | }
123 | }
124 |
125 | using namespace Treap;
126 |
127 | int const maxn = 303030;
128 |
129 | int n;
130 | vector g[maxn];
131 | treap t = nullptr;
132 | vector v[maxn];
133 | int gin[maxn];
134 | treap ed[maxn][2];
135 |
136 | namespace ET {
137 | void dfs(int u) {
138 | auto tu = new Node(u);
139 | ed[u][0] = tu;
140 | merge(t, t, tu);
141 |
142 | for (int v : g[u]) dfs(v);
143 |
144 | tu = new Node(u);
145 | ed[u][1] = tu;
146 | merge(t, t, tu);
147 | }
148 |
149 | void create() {
150 | for (int i = 1; i <= n; i++) {
151 | if (gin[i] == 0) {
152 | dfs(i);
153 | }
154 | }
155 | t->pai = nullptr;
156 | }
157 |
158 | treap get_subtree(int u, bool include = true) {
159 | int pos_u[2] = {pos(ed[u][0]) - include + 1, pos(ed[u][1]) + include};
160 |
161 | treap lu = nullptr, ru = nullptr;
162 | split(t, t, ru, pos_u[1]);
163 | split(t, lu, t, pos_u[0]);
164 |
165 | treap aux = t;
166 |
167 | merge(t, lu, ru);
168 |
169 | if (t) t->pai = nullptr;
170 | if (aux) aux->pai = nullptr;
171 |
172 | return aux;
173 | }
174 |
175 | tuple get_subtrees(int u) {
176 | int pos_u[2] = {pos(ed[u][0]), pos(ed[u][1]) + 1};
177 |
178 | treap lu = nullptr, ru = nullptr;
179 | split(t, t, ru, pos_u[1]);
180 | split(t, lu, t, pos_u[0]);
181 |
182 | if (t) t->pai = nullptr;
183 | if (lu) lu->pai = nullptr;
184 | if (ru) ru->pai = nullptr;
185 |
186 | return {lu, t, ru};
187 | }
188 |
189 | void merge_subtrees(treap l, treap sub, treap r) {
190 | merge(t, l, sub);
191 | merge(t, t, r);
192 | t->pai = nullptr;
193 | }
194 |
195 | void insert_subtree(int u, treap v) {
196 | int pos_u[2] = {pos(ed[u][0]) + 1, pos(ed[u][1])};
197 |
198 | treap aux = nullptr;
199 |
200 | split(t, t, aux, pos_u[0]);
201 |
202 | merge(t, t, v);
203 | merge(t, t, aux);
204 |
205 | t->pai = nullptr;
206 | }
207 |
208 | bool inside_subtree(int u, int v) {
209 | int pos_u[2] = {pos(ed[u][0]), pos(ed[u][1])};
210 | int pos_v = pos(ed[v][0]);
211 |
212 | return pos_u[0] <= pos_v and pos_v <= pos_u[1];
213 | }
214 | }
215 |
216 | int main() {
217 | ios_base::sync_with_stdio(false), cin.tie(nullptr);
218 |
219 | int m, q;
220 |
221 | cin >> n >> m >> q;
222 |
223 | for (int i = 0; i < m; i++) {
224 | int u, v;
225 | cin >> u >> v;
226 |
227 | gin[v]++;
228 | g[u].pb(v);
229 | }
230 |
231 | ET::create();
232 |
233 | while (q--) {
234 | string op;
235 | cin >> op;
236 |
237 | if (op == "swap") {
238 | int u, v;
239 | cin >> u >> v;
240 |
241 | if (ET::inside_subtree(u, v) or ET::inside_subtree(v, u)) {
242 | continue;
243 | }
244 |
245 | auto sub_u = ET::get_subtree(u, false);
246 | auto sub_v = ET::get_subtree(v, false);
247 |
248 | ET::insert_subtree(u, sub_v);
249 | ET::insert_subtree(v, sub_u);
250 | }
251 | else if (op == "append") {
252 | int u, v;
253 | cin >> u >> v;
254 |
255 | if (ET::inside_subtree(v, u)) {
256 | continue;
257 | }
258 |
259 | auto sub_v = ET::get_subtree(v);
260 |
261 | ET::insert_subtree(u, sub_v);
262 | }
263 | else if (op == "sauce") {
264 | int u, y;
265 | cin >> u >> y;
266 |
267 | auto [lu, sub_u, ru] = ET::get_subtrees(u);
268 |
269 | sub_u->lazy_sauce += y;
270 | push(sub_u);
271 |
272 | ET::merge_subtrees(lu, sub_u, ru);
273 |
274 | }
275 | else if (op == "cheese") {
276 | int u, y;
277 | cin >> u >> y;
278 |
279 | auto [lu, sub_u, ru] = ET::get_subtrees(u);
280 | treap t = nullptr;
281 |
282 | int p = pos(ed[u][1]);
283 | split(sub_u, sub_u, t, p);
284 | t->cheese += y;
285 | merge(sub_u, sub_u, t);
286 | sub_u->pai = nullptr;
287 |
288 | split(sub_u, t, sub_u, 2);
289 | t->cheese += y;
290 | merge(sub_u, t, sub_u);
291 | sub_u->pai = nullptr;
292 |
293 | ET::merge_subtrees(lu, sub_u, ru);
294 | }
295 | else if (op == "querySauce") {
296 | int u;
297 | cin >> u;
298 |
299 | auto [lu, sub_u, ru] = ET::get_subtrees(u);
300 | cout << sub_u->sum_sauce / 2 << '\n';
301 |
302 | ET::merge_subtrees(lu, sub_u, ru);
303 | }
304 | else if (op == "queryCheese") {
305 | int u;
306 | cin >> u;
307 |
308 | auto [lu, sub_u, ru] = ET::get_subtrees(u);
309 | cout << sub_u->sum_cheese / 2 << '\n';
310 |
311 | ET::merge_subtrees(lu, sub_u, ru);
312 | }
313 | }
314 | }
315 |
--------------------------------------------------------------------------------
/data_structures/li_chao.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | using ll = long long;
6 |
7 | int const maxn = 101010;
8 | ll const inf = 0x3f3f3f3;
9 |
10 | template>
11 | struct LiChao {
12 | private:
13 | struct Fc {
14 | ll a, b;
15 |
16 | ll eval(ll x) {
17 | return a*x + b;
18 | }
19 | };
20 |
21 | struct Node {
22 | Fc fn;
23 | unique_ptr l, r;
24 |
25 | Node(Fc fn) : fn(fn) {}
26 | };
27 |
28 | unique_ptr root;
29 |
30 | void upd(unique_ptr &t, ll l, ll r, Fc fn, Op op = Op{}) {
31 | ll m = (l+r)/2;
32 |
33 | bool bleft = op(fn.eval(l), t->fn.eval(l));
34 | bool bmid = op(fn.eval(m), t->fn.eval(m));
35 |
36 | if (bmid) swap(t->fn, fn);
37 | if (l >= r) return;
38 |
39 | if (bleft != bmid) {
40 | if (!t->l) t->l = make_unique(fn);
41 | else upd(t->l, l, m, fn);
42 | }
43 | else {
44 | if (!t->r) t->r = make_unique(fn);
45 | else upd(t->r, m+1, r, fn);
46 | }
47 | }
48 |
49 |
50 | ll get(unique_ptr &t, ll x, ll l, ll r) {
51 | ll m = (l+r)/2;
52 | if (l == r and l == x) return t->fn.eval(x);
53 |
54 | if (x <= m and t->l)
55 | return min(t->fn.eval(x), get(t->l, x, l, m));
56 | else if (x > m and t->r)
57 | return min(t->fn.eval(x), get(t->r, x, m+1, r));
58 |
59 | return t->fn.eval(x);
60 | }
61 | public:
62 | LiChao() : root(nullptr) {}
63 |
64 | void upd(ll a, ll b, ll l = 0, ll r = 1e6) {
65 | if (!root) {
66 | root = make_unique(Fc{a, b});
67 | return;
68 | }
69 | upd(root, l, r, {a, b});
70 | }
71 |
72 | ll get(ll x, ll l = 0, ll r = 1e6) {
73 | return get(root, x, l, r);
74 | }
75 | };
76 | ll a[maxn], b[maxn], dp[maxn];
77 |
78 | int main()
79 | {
80 | ios::sync_with_stdio(false), cin.tie(nullptr);
81 |
82 | int n;
83 | cin >> n;
84 |
85 | for (int i = 1; i <= n; i++) cin >> a[i];
86 | for (int i = 1; i <= n; i++) cin >> b[i];
87 |
88 | LiChao<> l;
89 |
90 | l.upd(b[1], 0);
91 |
92 | dp[1] = b[1];
93 |
94 | for (int i = 2; i <= n; i++) {
95 | dp[i] = l.get(a[i]);
96 | l.upd(b[i], dp[i]);
97 | }
98 |
99 | cout << dp[n] << "\n";
100 | }
--------------------------------------------------------------------------------
/data_structures/meldable_heap.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | struct node
6 | {
7 | int val;
8 |
9 | node *l, *r;
10 |
11 | node(int val)
12 | : val(val), l(nullptr), r(nullptr) {};
13 | };
14 |
15 | mt19937 rd;
16 | uniform_int_distribution toss(0, 1);
17 |
18 | node* meld(node *&l, node *&r)
19 | {
20 | if (!l) return r;
21 | if (!r) return l;
22 |
23 | if (l->val > r->val) swap(l, r);
24 |
25 | if (toss(rd)) l->l = meld(l->l, r);
26 | else l->r = meld(l->r, r);
27 |
28 | return l;
29 | }
30 |
31 | void insert(node *&t, int x)
32 | {
33 | node *aux = new node(x);
34 |
35 | t = meld(t, aux);
36 | }
37 |
38 | void pop(node *&t)
39 | {
40 | if (!t) return;
41 |
42 | t = meld(t->l, t->r);
43 | }
44 |
45 | int min(node *t)
46 | {
47 | return t? t->val: 0;
48 | }
49 |
50 | node *t = nullptr;
51 |
52 | int main()
53 | {
54 | insert(t, 2);
55 | insert(t, 3);
56 | insert(t, 4);
57 | print(t);
58 | cout << "\n";
59 | cout << min(t) << "\n";
60 | pop(t);
61 | cout << min(t) << "\n";
62 | }
--------------------------------------------------------------------------------
/data_structures/merge_sort_tree.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define LEFT ((no<<1)+1)
4 | #define RIGHT ((no<<1)+2)
5 |
6 | using namespace std;
7 |
8 | template
9 | struct mtree
10 | {
11 | vector tree[maxn*4];
12 | T* v;
13 |
14 | mtree() = default;
15 | mtree(T* vv) : v(vv) {};
16 |
17 | void build(int no, int l, int r)
18 | {
19 | if (l == r) return void(tree[no].push_back(v[l]));
20 |
21 | int m = (l+r)>>1;
22 |
23 | build(LEFT, l, m);
24 | build(RIGHT, m+1, r);
25 |
26 | merge(tree[LEFT].begin(), tree[LEFT].end(),
27 | tree[RIGHT].begin(), tree[RIGHT].end(),
28 | back_inserter(tree[no]));
29 | }
30 |
31 | inline int f(int no, int x, int y)
32 | {
33 | return upper_bound(tree[no].begin(), tree[no].end(), y) -
34 | lower_bound(tree[no].begin(), tree[no].end(), x);
35 | }
36 |
37 | int get(int no, int l, int r, int a, int b, int x, int y)
38 | {
39 | if (a <= l and r <= b) return f(no, x, y);
40 |
41 | int m = (l+r)>>1;
42 |
43 | if (b <= m) return get(LEFT, l, m, a, b, x, y);
44 | if (a > m) return get(RIGHT, m+1, r, a, b, x, y);
45 |
46 | return get(LEFT, l, m, a, b, x, y) +
47 | get(RIGHT, m+1, r, a, b, x, y);
48 | }
49 | };
50 |
51 | int main()
52 | {
53 | }
--------------------------------------------------------------------------------
/data_structures/merge_sort_tree_upd.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define LEFT ((no<<1)+1)
4 | #define RIGHT ((no<<1)+2)
5 |
6 | using namespace std;
7 |
8 | template
9 | struct treap
10 | {
11 | struct node
12 | {
13 | T val;
14 | int h, sz;
15 | node *l, *r;
16 |
17 | node(T v)
18 | : val(v), h(rand()), sz(1), l(nullptr), r(nullptr) {};
19 | };
20 |
21 | node *root;
22 |
23 | treap() : root(nullptr) {};
24 |
25 | int sz(node* t)
26 | {
27 | return t? t->sz : 0;
28 | }
29 |
30 | void op(node* t)
31 | {
32 | if (!t) return;
33 |
34 | t->sz = sz(t->l) + 1 + sz(t->r);
35 | }
36 |
37 | void merge(node *&t, node *l, node *r)
38 | {
39 | if (!l or !r) return void(t = l? l : r);
40 |
41 | if (l->h > r->h) merge(l->r, l->r, r), t = l;
42 | else merge(r->l, l, r->l), t = r;
43 |
44 | op(t);
45 | }
46 |
47 | void split(node *t, node *&l, node *&r, T val)
48 | {
49 | if (!t) return void(l = r = nullptr);
50 |
51 | if (val <= t->val) split(t->l, l, t->l, val), r = t;
52 | else split(t->r, t->r, r, val), l = t;
53 |
54 | op(l), op(r);
55 | }
56 |
57 | void insert(node *&t, node *v)
58 | {
59 | if (!t) return void(t = v);
60 |
61 | if (v->h > t->h) split(t, v->l, v->r, v->val), t = v;
62 | else if (v->val <= t->val) insert(t->l, v);
63 | else insert(t->r, v);
64 |
65 | op(t);
66 | }
67 |
68 | void erase(node *&t, T v)
69 | {
70 | if (!t) return;
71 |
72 | if (t->val == v) {
73 | node *tmp = t;
74 | merge(t, t->l, t->r);
75 | delete tmp;
76 | }
77 | else if (t->val > v) erase(t->l, v);
78 | else erase(t->r, v);
79 |
80 | op(t);
81 | }
82 |
83 | void insert(T val)
84 | {
85 | node *v = new node(val);
86 | insert(root, v);
87 | }
88 |
89 | void erase(T val)
90 | {
91 | erase(root, val);
92 | }
93 |
94 | int size()
95 | {
96 | return sz(root);
97 | }
98 |
99 | int cnt(T x, T y)
100 | {
101 | node *l = nullptr, *r = nullptr;
102 |
103 | split(root, l, root, x);
104 | split(root, root, r, y);
105 |
106 | int ans = sz(root);
107 |
108 | merge(root, l, root);
109 | merge(root, root, r);
110 |
111 | return ans;
112 | }
113 | };
114 |
115 | ostream& operator<<(ostream& out, const treap::node *t)
116 | {
117 | if (!t) return out;
118 |
119 | if (t->l) out << t->l;
120 | out << t->val << " ";
121 | if (t->r) out << t->r;
122 | return out;
123 | }
124 |
125 | ostream& operator<<(ostream& out, const treap& tp)
126 | {
127 | out << tp.root;
128 |
129 | return out;
130 | }
131 |
132 | template
133 | struct mtree
134 | {
135 | treap tree[maxn*3]{};
136 | T *v;
137 |
138 | mtree() = default;
139 |
140 | mtree(T *vv) : v(vv) {};
141 |
142 | void build(int no, int l, int r)
143 | {
144 | if (l == r) return void(tree[no].insert(v[l]));
145 |
146 | for (int i = l; i <= r; i++) tree[no].insert(v[i]);
147 |
148 | int m = (l+r)>>1;
149 |
150 | build(LEFT, l, m);
151 | build(RIGHT, m+1, r);
152 | }
153 |
154 | void upd(int no, int l, int r, int pos, T val)
155 | {
156 | tree[no].erase(v[pos]);
157 | tree[no].insert(val);
158 |
159 | if (l == r) return void(v[pos] = val);
160 |
161 | int m = (l+r)>>1;
162 |
163 | if (pos <= m) upd(LEFT, l, m, pos, val);
164 | else upd(RIGHT, m+1, r, pos, val);
165 | }
166 |
167 | // no of ocurrences of numbers of values [x,y) in [a,b]
168 | int get(int no, int l, int r, int a, int b, T x, T y)
169 | {
170 | if (a <= l and r <= b) return tree[no].cnt(x, y);
171 |
172 | int m = (l+r)>>1;
173 |
174 | if (b <= m) return get(LEFT, l, m, a, b, x, y);
175 | if (a > m) return get(RIGHT, m+1, r, a, b, x, y);
176 |
177 | return get(LEFT, l, m, a, b, x, y) +
178 | get(RIGHT, m+1, r, a, b, x, y);
179 | }
180 |
181 | void print(int no, int l, int r)
182 | {
183 | cout << tree[no] << "\n";
184 |
185 | int m = (l+r)>>1;
186 |
187 | if (l == r) return;
188 |
189 | print(LEFT, l, m);
190 | print(RIGHT, m+1, r);
191 | }
192 | };
193 |
194 | const int maxn = 101;
195 |
196 | int v[maxn];
197 | mtree t{v};
198 |
199 | int main()
200 | {
201 | int n;
202 | cin >> n;
203 |
204 | for (int i = 1; i <= n; i++)
205 | cin >> v[i];
206 |
207 | t.build(0, 1, n);
208 | t.print(0, 1, n);
209 | }
--------------------------------------------------------------------------------
/data_structures/minqueue.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define ff first
4 | #define ss second
5 |
6 | using namespace std;
7 |
8 | typedef pair ii;
9 |
10 | const int inf = 0x3f3f3f3f;
11 |
12 | struct minqueue
13 | {
14 | deque dq;
15 |
16 | int l, r;
17 |
18 | minqueue() {
19 |
20 | l = 1;
21 | r = 1;
22 | }
23 |
24 | void add(int x)
25 | {
26 | while(dq.size() >= 1 and dq.back().ff >= x) dq.pop_back();
27 |
28 | dq.push_back({x, r++});
29 | }
30 |
31 | void pop()
32 | {
33 | if (dq.front().ss == l++) dq.pop_front();
34 | }
35 |
36 | int get()
37 | {
38 | return dq.empty()? inf: dq[0].ff;
39 | }
40 | };
41 |
42 | int main()
43 | {
44 | return 0;
45 | }
--------------------------------------------------------------------------------
/data_structures/minqueue_sum.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define ff first
4 | #define ss second
5 |
6 | using namespace std;
7 |
8 | typedef pair ii;
9 |
10 | struct minqueue
11 | {
12 | deque dq;
13 |
14 | int l, r, sum;
15 |
16 | void clear()
17 | {
18 | l = r = sum = 0;
19 | dq.clear();
20 | }
21 |
22 | void push(int x)
23 | {
24 | while (!dq.empty() and dq.back().ff > x-sum) dq.pop_back();
25 | dq.push_back({x-sum,r});
26 | r++;
27 | }
28 |
29 | void pop()
30 | {
31 | if (!dq.empty() and dq.front().ss == l) dq.pop_front();
32 | l++;
33 | }
34 |
35 | void add(int x) {sum += x;}
36 |
37 | int getmin() {return dq[0].ff+sum;}
38 |
39 | int size() {return r-l;}
40 | };
41 |
42 | const int maxn = 1000;
43 | const int maxm = 100000;
44 | const int inf = 0x3f3f3f;
45 |
46 | minqueue q[maxm];
47 |
48 | int d[maxm];
49 | int w[maxn], e[maxn], c[maxn];
50 |
51 | int main()
52 | {
53 | int n, m;
54 | cin >> n >> m;
55 |
56 | for (int i = 1; i <= n; i++) cin >> w[i] >> e[i] >> c[i];
57 |
58 | for (int i = 1; i <= m; i++) d[i] = inf;
59 |
60 | for (int i = 1; i <= n; i++) {
61 |
62 | for (int j = 0; j < w[i]; j++) q[j].clear();
63 |
64 | for (int j = 0; j <= m; j++) {
65 |
66 | minqueue& mq = q[j%w[i]];
67 |
68 | if (mq.size() > e[i]) mq.pop();
69 |
70 | mq.add(c[i]);
71 | mq.push(d[j]);
72 |
73 | d[j] = mq.getmin();
74 | }
75 | }
76 |
77 | for (int i = 0; i <= m; i++) cout << d[i] << " ";
78 | cout << "\n";
79 | }
--------------------------------------------------------------------------------
/data_structures/mo.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 101010;
6 | const int maxq = 101010;
7 |
8 | struct Query
9 | {
10 | int l, bk, r, id;
11 |
12 | bool operator<(Query const& rhs) {
13 | if (bk == rhs.bk) {
14 | if (bk&1) return r > rhs.r;
15 | else return r < rhs.r;
16 | }
17 | return bk < rhs.bk;
18 | }
19 | };
20 |
21 | int ans;
22 | int v[maxn], res[maxn];
23 | Query qr[maxq];
24 |
25 | void add(int x)
26 | {
27 |
28 | }
29 |
30 | void rem(int x)
31 | {
32 |
33 | }
34 |
35 | int main()
36 | {
37 | int n, q;
38 | cin >> n >> q;
39 |
40 | int sqt = sqrt(n)+1;
41 |
42 | for (int i = 0; i < n; i++)
43 | cin >> v[i];
44 |
45 | for (int i = 0; i < q; i++)
46 | cin >> qr[i].l >> qr[i].r, qr[i].bk = qr[i].l/sqt, qr[i].id = i;
47 |
48 | sort(qr, qr+q);
49 |
50 | int cl = 0, cr = -1;
51 | for (int i = 0; i < q; i++) {
52 | int l = qr[i].l, r = qr[i].r;
53 |
54 | while (cr < r) add(++cr);
55 | while (cl > l) add(--cl);
56 | while (cr > r) rem(cr--);
57 | while (cl < l) rem(cl++);
58 |
59 | res[qr[i].id] = ans;
60 | }
61 |
62 | for (int i = 0; i < q; i++)
63 | cout << res[i] << "\n";
64 | }
--------------------------------------------------------------------------------
/data_structures/mo_hilbert.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | typedef long long ll;
6 |
7 | const int maxn = 100010;
8 | const int sqt = 330;
9 |
10 | inline int64_t ord(int x, int y, int pow, int rotate) {
11 | if (pow == 0) {
12 | return 0;
13 | }
14 | int hpow = 1 << (pow-1);
15 | int seg = (x < hpow) ? (
16 | (y < hpow) ? 0 : 3
17 | ) : (
18 | (y < hpow) ? 1 : 2
19 | );
20 | seg = (seg + rotate) & 3;
21 | const int rotateDelta[4] = {3, 0, 0, 1};
22 | int nx = x & (x ^ hpow), ny = y & (y ^ hpow);
23 | int nrot = (rotate + rotateDelta[seg]) & 3;
24 | int64_t subSquareSize = int64_t(1) << (2*pow - 2);
25 | int64_t ans = seg * subSquareSize;
26 | int64_t add = ord(nx, ny, pow-1, nrot);
27 | ans += (seg == 1 || seg == 2) ? add : (subSquareSize - add - 1);
28 | return ans;
29 | }
30 |
31 | struct query
32 | {
33 | int l, r, id;
34 | ll w;
35 |
36 | bool operator<(const query &rhs) const {
37 | return w < rhs.w;
38 | }
39 | };
40 |
41 | int lim = 0;
42 |
43 | struct bit
44 | {
45 | int b[maxn];
46 |
47 | inline void add(int x, int d)
48 | {
49 | for (int i = x; i <= lim; i += i&-i) b[i] += d;
50 | }
51 |
52 | inline int get(int x)
53 | {
54 | int ans = 0;
55 | for (int i = x; i > 0; i -= i&-i) ans += b[i];
56 | return ans;
57 | }
58 | };
59 |
60 | bit re;
61 | query qr[maxn];
62 | int v[maxn], v2[maxn];
63 |
64 | ll tot = 0;
65 | ll sum = 0;
66 |
67 | inline void addl(int x)
68 | {
69 | tot++;
70 | re.add(v[x], 1);
71 | sum += re.get(v[x]-1);
72 | }
73 |
74 | inline void addr(int x)
75 | {
76 | tot++;
77 | re.add(v[x], 1);
78 | sum += tot - re.get(v[x]);
79 | }
80 |
81 | inline void reml(int x)
82 | {
83 | tot--;
84 | re.add(v[x], -1);
85 | sum -= re.get(v[x]-1);
86 | }
87 |
88 | inline void remr(int x)
89 | {
90 | tot--;
91 | re.add(v[x], -1);
92 | sum -= tot - re.get(v[x]);
93 | }
94 |
95 | ll res[maxn];
96 |
97 |
98 |
99 | inline int readChar();
100 | template inline T readInt();
101 | template inline void writeInt( T x, char end = 0 );
102 | inline void writeChar( int x );
103 | inline void writeWord( const char *s );
104 |
105 | /** Read */
106 |
107 | static const int buf_size = 4096;
108 |
109 | inline int getChar() {
110 | static char buf[buf_size];
111 | static int len = 0, pos = 0;
112 | if (pos == len)
113 | pos = 0, len = fread(buf, 1, buf_size, stdin);
114 | if (pos == len)
115 | return -1;
116 | return buf[pos++];
117 | }
118 |
119 | inline int readChar() {
120 | int c = getChar();
121 | while (c <= 32)
122 | c = getChar();
123 | return c;
124 | }
125 |
126 | template
127 | inline T readInt() {
128 | char c = readChar();
129 | T x = 0;
130 | while ('0' <= c && c <= '9')
131 | x = x * 10 + c - '0', c = getChar();
132 | return x;
133 | }
134 |
135 | /** Write */
136 |
137 | static int write_pos = 0;
138 | static char write_buf[buf_size];
139 |
140 | inline void writeChar( int x ) {
141 | if (write_pos == buf_size)
142 | fwrite(write_buf, 1, buf_size, stdout), write_pos = 0;
143 | write_buf[write_pos++] = x;
144 | }
145 |
146 | template
147 | inline void writeInt( T x, char end ) {
148 | if (x < 0)
149 | writeChar('-'), x = -x;
150 |
151 | char s[24];
152 | int n = 0;
153 | while (x || !n)
154 | s[n++] = '0' + x % 10, x /= 10;
155 | while (n--)
156 | writeChar(s[n]);
157 | if (end)
158 | writeChar(end);
159 | }
160 |
161 | inline void writeWord( const char *s ) {
162 | while (*s)
163 | writeChar(*s++);
164 | }
165 |
166 | struct Flusher {
167 | ~Flusher() {
168 | if (write_pos)
169 | fwrite(write_buf, 1, write_pos, stdout), write_pos = 0;
170 | }
171 | } flusher;
172 |
173 |
174 |
175 | int main()
176 | {
177 | int n;
178 | n = readInt();
179 |
180 | ll nn = 0;
181 | while ((1< cr) addr(++cr);
219 | while (r < cr) remr(cr--);
220 | while (l < cl) addl(--cl);
221 | while (l > cl) reml(cl++);
222 |
223 | res[id] = sum;
224 | }
225 |
226 | for (int i = 0; i < q; i++) writeInt(res[i],'\n');
227 |
228 | return 0;
229 | }
--------------------------------------------------------------------------------
/data_structures/persistent_seg_dinamic.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define ff first
4 | #define ss second
5 | #define MID ((l+r)/2)
6 |
7 | using namespace std;
8 |
9 | typedef pair ii;
10 |
11 | const int maxn = 100010;
12 |
13 | struct node
14 | {
15 | int sum;
16 |
17 | node *l, *r;
18 |
19 | node() {
20 |
21 | l = r = nullptr;
22 |
23 | sum = 0;
24 | }
25 | };
26 |
27 | typedef node* pnode;
28 |
29 | int n;
30 | ii v[maxn];
31 | int v2[maxn];
32 | pnode root[maxn];
33 |
34 | int sum(pnode t)
35 | {
36 | return t? t->sum: 0;
37 | }
38 |
39 | pnode build(int l, int r)
40 | {
41 | pnode cur = new node();
42 |
43 | if (l == r) return cur;
44 |
45 | cur->l = build(l, MID);
46 | cur->r = build(MID+1, r);
47 |
48 | return cur;
49 | }
50 |
51 | pnode update(pnode idx, int l, int r, int pos, int val)
52 | {
53 | pnode cur = new node();
54 |
55 | cur->sum = idx->sum;
56 | cur->l = idx->l;
57 | cur->r = idx->r;
58 |
59 | if (l == r) {
60 |
61 | cur->sum = val;
62 | return cur;
63 | }
64 |
65 | if (pos <= MID) cur->l = update(cur->l, l, MID, pos, val);
66 | else cur->r = update(cur->r, MID+1, r, pos, val);
67 |
68 | cur->sum = sum(cur->l) + sum(cur->r);
69 |
70 | return cur;
71 | }
72 |
73 | int query(pnode idx, int l, int r, int a, int b)
74 | {
75 | if (a <= l and b >= r) return sum(idx);
76 |
77 | if (l > b or r < a) return 0;
78 |
79 | int lchild = query(idx->l, l, MID, a, b);
80 | int rchild = query(idx->r, MID+1, r, a, b);
81 |
82 | return lchild+rchild;
83 | }
84 |
85 | int get(int a, int b, int k)
86 | {
87 | int l = 1, r = n, idx;
88 |
89 | while (l != r) {
90 |
91 | idx = (l+r)/2;
92 |
93 | int num = query(root[idx], 1, n, a, b);
94 |
95 | // cout << l << " " << idx << " " << r << " " << num << "\n";
96 |
97 | if (num < k) l = idx+1;
98 | else r = idx;
99 | }
100 |
101 | idx = (l+r)/2;
102 |
103 | return idx;
104 | }
105 |
106 | int c[maxn];
107 |
108 | int main()
109 | {
110 | cin >> n;
111 |
112 | for (int i = 1; i <= n; i++) cin >> v[i].ff, v[i].ss = i, v2[i] = v[i].ff;
113 |
114 | map mp;
115 |
116 | sort(v2+1, v2+n+1);
117 |
118 | int id = 1;
119 |
120 | for (int i = 1; i <= n; i++) {
121 |
122 | if (mp[v2[i]] == 0) mp[v2[i]] = id, c[id++] = v2[i];
123 | }
124 |
125 | for (int i = 1; i <= n; i++) v[i].ff = mp[v[i].ff];
126 |
127 | sort(v+1, v+n+1);
128 |
129 | root[0] = build(1, n);
130 |
131 | for (int i = 1; i <= n; i++) {
132 |
133 | root[i] = update(root[i-1], 1, n, v[i].ss, 1);
134 | }
135 |
136 | int q;
137 | cin >> q;
138 |
139 | while(q--) {
140 |
141 | int l, r, k;
142 | cin >> l >> r >> k;
143 |
144 | // int ans = query(root[k], 1, n, l, r);
145 |
146 | // cout << "\n";
147 | int ans = get(l, r, k);
148 | // cout << "\n";
149 |
150 | // cout << ans << "\n";
151 | cout << c[ans] << "\n";
152 | }
153 |
154 | return 0;
155 | }
--------------------------------------------------------------------------------
/data_structures/persistent_treap.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 101010;
6 |
7 | template
8 | class Treap {
9 | private:
10 | struct Node
11 | {
12 | Node *l, *r;
13 | int h, sz;
14 | T val;
15 | bool old;
16 |
17 | Node(T const& val)
18 | : l(nullptr), r(nullptr), h(rand()), sz(1), val(val), old(false) {};
19 |
20 | Node(Node* t)
21 | {
22 | *this = *t;
23 | old = true;
24 | }
25 | };
26 |
27 | Node *root;
28 |
29 | int sz(Node *t)
30 | {
31 | return t? t->sz : 0;
32 | }
33 |
34 | void op(Node *t)
35 | {
36 | if (!t) return;
37 |
38 | t->sz = sz(t->l) + sz(t->r) + 1;
39 | }
40 |
41 | void clone(Node *t)
42 | {
43 | if (!t) return;
44 |
45 | if (t->old == false) return;
46 |
47 | if (t->l) t->l = new Node(t->l);
48 | if (t->r) t->r = new Node(t->r);
49 |
50 | t->old = true;
51 | }
52 |
53 | void merge(Node *&t, Node *l, Node *r)
54 | {
55 | clone(l), clone(r);
56 |
57 | if (!l or !r) return void (t = l? l: r);
58 |
59 | if (l->h > r->h) merge(l->r, l->r, r), t = l;
60 | else merge(r->l, l, r->l), t = r;
61 |
62 | op(t);
63 | }
64 |
65 | void split(Node *t, Node *&l, Node *&r, T val)
66 | {
67 | clone(t);
68 |
69 | if (!t) return void(l = r = nullptr);
70 |
71 | if (t->val < val) split(t->r, t->r, r, val), l = t;
72 | else split(t->l, l, t->l, val), r = t;
73 |
74 | op(l), op(r);
75 | }
76 |
77 | void insert(Node *&t, Node *v)
78 | {
79 | clone(t);
80 |
81 | if (!t) t = v;
82 | else if (v->h > t->h)
83 | split(t, v->l, v->r, v->val), t = v;
84 | else if (t->val < v->val) insert(t->r, v);
85 | else insert(t->l, v);
86 |
87 | op(t);
88 | }
89 |
90 | void erase(Node *&t, T v)
91 | {
92 | clone(t);
93 |
94 | if (!t) return;
95 | if (t->val == v) {
96 | Node *tmp = t;
97 | merge(t, t->l, t->r);
98 | delete tmp;
99 | }
100 | else if (t->val < v) erase(t->r, v);
101 | else erase(t->l, v);
102 |
103 | op(t);
104 | }
105 |
106 | T const& kth(Node *t, int k)
107 | {
108 | int pos = sz(t->l) + 1;
109 |
110 | if (k == pos) return t->val;
111 | else if (pos > k) return kth(t->l, k);
112 | else return kth(t->r, k-pos);
113 | }
114 |
115 | public:
116 | Treap() : root(nullptr) {} ;
117 |
118 | ~Treap() = default;
119 | // n sei o que fazer :/
120 |
121 | Treap(Treap const& tp) : root(new Node(tp.root)) {};
122 |
123 | Treap(Treap&& tp) : root(tp.root) {};
124 |
125 | Treap& operator=(Treap const& tp) {
126 | root = new Node(tp.root);
127 | return *this;
128 | }
129 |
130 | Treap& operator=(Treap&& tp) {
131 | root = tp.root;
132 | return *this;
133 | }
134 |
135 | void insert(T const& v)
136 | {
137 | Node *t = new Node(v);
138 | insert(root, t);
139 | }
140 |
141 | void erase(T const& v)
142 | {
143 | erase(root, v);
144 | }
145 |
146 | T const& kth(int k)
147 | {
148 | return kth(root, k+1);
149 | }
150 | };
151 |
152 | Treap v[maxn];
153 |
154 | int main()
155 | {
156 | v[0].insert(4);
157 |
158 | v[1] = v[0];
159 | v[1].insert(6);
160 |
161 | v[2] = v[1];
162 | v[2].erase(4);
163 |
164 | cout << v[0].kth(0) << "\n";
165 | cout << v[1].kth(0) << " " << v[1].kth(1) << "\n";
166 | cout << v[2].kth(0) << "\n";
167 | }
--------------------------------------------------------------------------------
/data_structures/seg.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define LEFT ((no<<1)+1)
4 | #define RIGHT ((no<<1)+2)
5 |
6 | using namespace std;
7 |
8 | const int maxn = 101010;
9 |
10 | template
11 | struct seg
12 | {
13 | T tree[maxn*3];
14 | T *v;
15 |
16 | seg() = default;
17 |
18 | seg(T* vv) : v(vv) {};
19 |
20 | T op(T a, T b)
21 | {
22 | return min(a, b);
23 | }
24 |
25 | void build(int no, int l, int r)
26 | {
27 | if (l == r) return void(tree[no] = v[l]);
28 |
29 | int m = (l+r)>>1;
30 |
31 | build(LEFT, l, m);
32 | build(RIGHT, m+1, r);
33 |
34 | tree[no] = op(tree[LEFT], tree[RIGHT]);
35 | }
36 |
37 | T get(int no, int l, int r, int a, int b)
38 | {
39 | if (a <= l and r <= b) return tree[no];
40 |
41 | int m = (l+r)>>1;
42 |
43 | if (b <= m) return get(LEFT, l, m, a, b);
44 | if (a > m) return get(RIGHT, m+1, r, a, b);
45 |
46 | return op(get(LEFT, l, m, a, b),
47 | get(RIGHT, m+1, r, a, b));
48 | }
49 |
50 | void upd(int no, int l, int r, int p, T val)
51 | {
52 | if (l == r) return void(tree[no] = val);
53 |
54 | int m = (l+r)>>1;
55 |
56 | if (p <= m) upd(LEFT, l, m, p, val);
57 | else upd(RIGHT, m+1, r, p, val);
58 |
59 | tree[no] = op(tree[LEFT], tree[RIGHT]);
60 | }
61 | };
62 |
63 | int v[maxn];
64 | seg s[10];
65 |
66 | int main()
67 | {
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/data_structures/seg2d.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | int const maxn = 1001;
6 |
7 | int n, m;
8 | int v[maxn][maxn];
9 |
10 | int op(int x, int y)
11 | {
12 | return gcd(x, y);
13 | }
14 |
15 | class Seg
16 | {
17 | int tree[1<<11][1<<11];
18 |
19 | void build_y(int nox, int noy, int lx, int rx, int ly, int ry)
20 | {
21 | if (ly == ry) {
22 | if (lx == rx) tree[nox][noy] = v[lx][ly];
23 | else tree[nox][noy] = op(tree[nox*2+1][noy], tree[nox*2+2][noy]);
24 | }
25 | else {
26 | int my = (ly+ry)/2;
27 | build_y(nox, noy*2+1, lx, rx, ly, my);
28 | build_y(nox, noy*2+2, lx, rx, my+1, ry);
29 | tree[nox][noy] = op(tree[nox][noy*2+1], tree[nox][noy*2+2]);
30 | }
31 | }
32 |
33 | void build_x(int nox, int lx, int rx)
34 | {
35 | if (lx != rx) {
36 | int mx = (lx+rx)/2;
37 | build_x(nox*2+1, lx, mx);
38 | build_x(nox*2+2, mx+1, rx);
39 | }
40 | build_y(nox, 0, lx, rx, 1, m);
41 | }
42 |
43 | int get_y(int nox, int noy, int ly, int ry, int a, int b)
44 | {
45 | if (a <= ly and ry <= b) return tree[nox][noy];
46 |
47 | int my = (ly+ry)/2;
48 |
49 | if (b <= my) return get_y(nox, noy*2+1, ly, my, a, b);
50 | if (a > my) return get_y(nox, noy*2+2, my+1, ry, a, b);
51 |
52 | return op(get_y(nox, noy*2+1, ly, my, a, b),
53 | get_y(nox, noy*2+2, my+1, ry, a, b));
54 | }
55 |
56 | int get_x(int nox, int lx, int rx, int a, int b, int ay, int by)
57 | {
58 | if (a <= lx and rx <= b) return get_y(nox, 0, 1, m, ay, by);
59 |
60 | int mx = (lx+rx)/2;
61 |
62 | if (b <= mx) return get_x(nox*2+1, lx, mx, a, b, ay, by);
63 | if (a > mx) return get_x(nox*2+2, mx+1, rx, a, b, ay, by);
64 |
65 | return op(get_x(nox*2+1, lx, mx, a, b, ay, by),
66 | get_x(nox*2+2, mx+1, rx, a, b, ay, by));
67 | }
68 |
69 | void upd_y(int nox, int noy, int lx, int rx, int ly, int ry,
70 | int x, int y, int val)
71 | {
72 | if (ly == ry) {
73 | if (lx == rx) tree[nox][noy] = val;
74 | else tree[nox][noy] = op(tree[nox*2+1][noy], tree[nox*2+2][noy]);
75 | }
76 | else {
77 | int my = (ly+ry)/2;
78 | if (y <= my) upd_y(nox, noy*2+1, lx, rx, ly, my, x, y, val);
79 | else upd_y(nox, noy*2+2, lx, rx, my+1, ry, x, y, val);
80 | tree[nox][noy] = op(tree[nox][noy*2+1], tree[nox][noy*2+2]);
81 | }
82 | }
83 |
84 | void upd_x(int nox, int lx, int rx, int x, int y, int val)
85 | {
86 | if (lx != rx) {
87 | int mx = (lx+rx)/2;
88 | if (x <= mx) upd_x(nox*2+1, lx, mx, x, y, val);
89 | else upd_x(nox*2+2, mx+1, rx, x, y, val);
90 | }
91 | upd_y(nox, 0, lx, rx, 1, m, x, y, val);
92 | }
93 |
94 | public:
95 | void build()
96 | {
97 | build_x(0, 1, n);
98 | }
99 |
100 | void upd(int x, int y, int val)
101 | {
102 | upd_x(0, 1, n, x, y, val);
103 | }
104 |
105 | int get(int lx, int rx, int ly, int ry)
106 | {
107 | return get_x(0, 1, n, lx, rx, ly, ry);
108 | }
109 | };
110 |
111 | int main()
112 | {
113 |
114 | }
--------------------------------------------------------------------------------
/data_structures/seg_class.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | template
4 | class Seg {
5 | private:
6 | using join_t = std::function;
7 | using fix_t = std::function;
8 |
9 | int n;
10 | join_t const join;
11 | fix_t const fix = [] (T& a, T const& b) { a = b;};
12 |
13 | std::vector tree;
14 |
15 | template
16 | T const& build(int no, int l, int r, Iter const& v)
17 | {
18 | if (l == r)
19 | return tree[no] = v[l];
20 |
21 | int m = (l+r)/2;
22 |
23 | build(no*2+1, l, m, v);
24 | build(no*2+2, m+1, r, v);
25 |
26 | tree[no] = join(build(no*2+1, l, m, v),
27 | build(no*2+2, m+1, r, v));
28 |
29 | return tree[no];
30 | }
31 |
32 | void upd(int no, int l, int r, int pos, T val)
33 | {
34 | if (l == r) {
35 | fix(tree[no], val);
36 | return;
37 | }
38 |
39 | int m = (l+r)/2;
40 |
41 | if (pos <= m) upd(no*2+1, l, m, pos, val);
42 | else upd(no*2+2, m+1, r, pos, val);
43 |
44 | tree[no] = join(tree[no*2+1], tree[no*2+2]);
45 | }
46 |
47 | T get(int no, int l, int r, int a, int b)
48 | {
49 | if (a <= l and r <= b) return tree[no];
50 |
51 | int m = (l+r)/2;
52 |
53 | if (b <= m) return get(no*2+1, l, m, a, b);
54 | if (a > m) return get(no*2+2, m+1, r, a, b);
55 |
56 | return join(get(no*2+1, l, m, a, b),
57 | get(no*2+2, m+1, r, a, b));
58 | }
59 |
60 | public:
61 | Seg(int n_, join_t op_) :
62 | join(op_), n(n_), tree(n*4) {};
63 |
64 | Seg(int n_, join_t op_, fix_t fix_) :
65 | join(op_), n(n_), fix(fix_), tree(n*4) {};
66 |
67 | Seg(std::vector const& v, join_t op_) :
68 | join(op_), n(v.size()), tree(v.size()*4)
69 | {
70 | build(0, 0, n-1, v.data());
71 | }
72 |
73 | Seg(std::vector const& v, join_t op_, fix_t fix_) :
74 | join(op_), n(v.size()), fix(fix_), tree(v.size()*4)
75 | {
76 | build(0, 0, n-1, v.data());
77 | }
78 |
79 | template
80 | Seg(Iter const& begin, Iter const& end, join_t op_) :
81 | join(op_), n(end-begin), tree(4*(end-begin))
82 | {
83 | build(0, 0, n-1, begin);
84 | }
85 |
86 | template
87 | Seg(Iter const& begin, Iter const& end, join_t op_, fix_t fix_) :
88 | join(op_), n(end-begin), fix(fix_), tree(4*(end-begin))
89 | {
90 | build(0, 0, n-1, begin);
91 | }
92 |
93 | void upd(int pos, T val)
94 | {
95 | upd(0, 0, n-1, pos, val);
96 | }
97 |
98 | T get(int l, int r)
99 | {
100 | return get(0, 0, n-1, l, r);
101 | }
102 | };
103 |
104 | // example (Baldes - OBI2018)
105 | namespace Problem
106 | {
107 | struct Node
108 | {
109 | int mini, maxi, ans;
110 | };
111 |
112 | Node join(Node const& a, Node const& b)
113 | {
114 | Node ans;
115 | ans.mini = std::min(a.mini, b.mini);
116 | ans.maxi = std::max(a.maxi, b.maxi);
117 | ans.ans = std::max({a.ans, b.ans,
118 | abs(a.maxi-b.mini),
119 | abs(b.maxi-a.mini)});
120 | return ans;
121 | }
122 |
123 | void fix(Node& a, Node const& b)
124 | {
125 | a.mini = std::min(a.mini, b.mini);
126 | a.maxi = std::max(a.maxi, b.maxi);
127 | }
128 | }
129 |
130 | int main()
131 | {
132 | int n, q;
133 | std::cin >> n >> q;
134 |
135 | std::vector v(n);
136 | for (int i = 0; i < n; i++)
137 | std::cin >> v[i].mini, v[i].maxi = v[i].mini;
138 |
139 | auto sg = Seg(v.begin(), v.end(), Problem::join, Problem::fix);
140 |
141 | while (q--) {
142 |
143 | int op;
144 | std::cin >> op;
145 |
146 | if (op == 1) {
147 | int val, pos;
148 | std::cin >> val >> pos;
149 |
150 | sg.upd(pos-1, {val, val, 0});
151 | }
152 | else {
153 | int l, r;
154 | std::cin >> l >> r;
155 |
156 | std::cout << sg.get(l-1, r-1).ans << "\n";
157 | }
158 | }
159 | }
--------------------------------------------------------------------------------
/data_structures/seg_iter.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using std::vector;
4 |
5 | // indexado do 1
6 | struct Seg {
7 | struct Node {
8 | int v;
9 |
10 | Node& add(Node const& rhs) {
11 | this->v += rhs.v;
12 | return *this;
13 | }
14 |
15 | static Node join(Node const& lhs, Node const& rhs) {
16 | Node r = lhs;
17 | r.add(rhs);
18 | return r;
19 | }
20 | };
21 |
22 | int n;
23 | vector tree;
24 |
25 | Seg(vector const& v) : n(v.size()), tree(n*3) {
26 | for (int i = 0; i < this->n; i++) {
27 | update(i+1, v[i]);
28 | }
29 | }
30 |
31 | inline Node query(int l, int r) {
32 | Node ans{};
33 | for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
34 | if(l&1) ans.add(tree[l++]);
35 | if(r&1) ans.add(tree[--r]);
36 | }
37 | return ans;
38 | }
39 |
40 | inline void update(int p, int val) {
41 | for(tree[p += n] = Node{val}; p > 1; p >>= 1) {
42 | tree[p >> 1] = Node::join(tree[p], tree[p^1]);
43 | }
44 | }
45 |
46 | inline Node get(int a, int b) {
47 | return query(a+1, b+1);
48 | }
49 |
50 | inline void clear(int pos, int val) {
51 | update(pos+1, val);
52 | }
53 | };
54 |
55 | int main() {
56 |
57 | }
--------------------------------------------------------------------------------
/data_structures/sparse_table.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | template
6 | struct SparseTable
7 | {
8 | int table[size][lsize];
9 |
10 | int msb(int x)
11 | {
12 | return 31 - __builtin_clz(x);
13 | }
14 |
15 | void build(int *v, int n)
16 | {
17 | for (int i = 1; i <= n; i++)
18 | table[i][0] = v[i];
19 |
20 | for (int bk = 1; bk < lsize; bk++) {
21 | for (int i = 1; i <= n; i++) {
22 | int ni = i + (1<<(bk-1));
23 | table[i][bk] = max(table[i][bk-1], table[ni][bk-1]);
24 | }
25 | }
26 | }
27 |
28 | int get(int l, int r)
29 | {
30 | int sz = r-l;
31 | if (sz == 0) return table[l][0];
32 |
33 | int szb = msb(sz);
34 | int rr = r-(1< st;
44 |
45 | int main()
46 | {
47 | }
--------------------------------------------------------------------------------
/data_structures/splay.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | template>
6 | class Splay {
7 | private:
8 | struct Node {
9 | Node *p;
10 | Node *l, *r;
11 |
12 | T val;
13 |
14 | Node(T const& v) : p(nullptr), l(nullptr), r(nullptr), val(v) {};
15 | };
16 |
17 | Node *root;
18 | int64_t sz;
19 | Comp comp;
20 |
21 | void lrot(Node *x) {
22 | Node *y = x->r;
23 | if (y) {
24 | x->r = y->l;
25 | if (y->l) y->l->p = x;
26 | y->p = x->p;
27 | }
28 | if (!x->p) root = y;
29 | else if (x->p->l == x) x->p->l = y;
30 | else if (x->p->r == x) x->p->r = y;
31 | if (y) y->l = x;
32 | x->p = y;
33 | }
34 |
35 | void rrot(Node *x) {
36 | Node *y = x->l;
37 | if (y) {
38 | x->l = y->r;
39 | if (y->r) y->r->p = x;
40 | y->p = x->p;
41 | }
42 | if (!x->p) root = y;
43 | else if (x->p->l == x) x->p->l = y;
44 | else if (x->p->r == x) x->p->r = y;
45 | if (y) y->r = x;
46 | x->p = y;
47 | }
48 |
49 | void splay(Node *x) {
50 | while (x->p) {
51 | if (!x->p->p) {
52 | if (x->p->l == x) rrot(x->p);
53 | else lrot(x->p);
54 | }
55 | else if (x->p->l == x and x->p->p->l == x->p) {
56 | rrot(x->p->p);
57 | rrot(x->p);
58 | }
59 | else if (x->p->r == x and x->p->p->r == x->p) {
60 | lrot(x->p->p);
61 | lrot(x->p);
62 | }
63 | else if (x->p->l == x and x->p->p->r == x->p) {
64 | rrot(x->p);
65 | lrot(x->p);
66 | }
67 | else {
68 | lrot(x->p);
69 | rrot(x->p);
70 | }
71 | }
72 | }
73 |
74 | void replace(Node *x, Node *y) {
75 | if (!x->p) root = y;
76 | else if (x == x->p->l) x->p->l = y;
77 | else x->p->r = y;
78 | if (y) y->p = x->p;
79 | }
80 |
81 | void insert(Node *&x, Node *y, Node *p) {
82 | if (!x) {
83 | x = y;
84 | y->p = p;
85 | splay(y);
86 | }
87 | else if (comp(y->val, x->val)) insert(x->l, y, x);
88 | else insert(x->r, y, x);
89 | }
90 |
91 | Node* find(Node *t, T const& v) {
92 | if (!t) return nullptr;
93 | else if (t->val == v) {
94 | splay(t);
95 | return root;
96 | }
97 | else if (comp(v, t->val)) return find(t->l, v);
98 | else return find(t->r, v);
99 | }
100 |
101 | void print(Node *t) {
102 | if (!t) return;
103 | print(t->l);
104 | cout << t->val << " ";
105 | print(t->r);
106 | }
107 |
108 | Node* find_min(Node *t) {
109 | if (!t) return nullptr;
110 | else if (t->l) return find_min(t->l);
111 | else return t;
112 | }
113 |
114 | Node* find_max(Node *t) {
115 | if (!t) return nullptr;
116 | else if (t->r) return find_max(t->r);
117 | else return t;
118 | }
119 |
120 | Node* join(Node *l, Node *r) {
121 | l = find_max(l), r = find_min(r);
122 | splay(l);
123 | splay(r);
124 | l->r = r;
125 | r->p = l;
126 |
127 | return l;
128 | }
129 |
130 | public:
131 | Splay() : root(nullptr), sz(0), comp() {};
132 |
133 | void insert(T const& v) {
134 | Node *t = new Node(v);
135 | insert(root, t, nullptr);
136 | sz++;
137 | }
138 |
139 | Node const* find(T const& v) {
140 | return find(root, v);
141 | }
142 |
143 | void erase(T const& v) {
144 | Node *t = find(root, v);
145 | if (!t) return;
146 |
147 | sz--;
148 |
149 | if (!t->l) replace(t, t->r);
150 | else if (!t->r) replace(t, t->l);
151 | else {
152 | replace(t, join(t->l, t->r));
153 | delete t;
154 | }
155 | }
156 |
157 | int64_t size() const {
158 | return sz;
159 | }
160 |
161 | void print() {
162 | print(root);
163 | cout << "\n";
164 | }
165 | };
166 |
167 | int main() {
168 | Splay st;
169 |
170 | st.insert(2);
171 | st.insert(4);
172 | st.insert(3);
173 | st.insert(5);
174 |
175 | assert(!st.find(1));
176 | assert(st.find(2));
177 | assert(st.find(3));
178 | assert(st.find(4));
179 | assert(st.find(5));
180 | assert(!st.find(6));
181 |
182 | st.print();
183 |
184 | st.erase(2);
185 | st.erase(4);
186 |
187 | assert(!st.find(1));
188 | assert(!st.find(2));
189 | assert(st.find(3));
190 | assert(!st.find(4));
191 | assert(st.find(5));
192 | assert(!st.find(6));
193 |
194 | st.print();
195 | }
--------------------------------------------------------------------------------
/data_structures/sqrttree.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | template
6 | T operation(T a, T b)
7 | {
8 | return a + b;
9 | }
10 |
11 | template
12 | struct node
13 | {
14 | T *v;
15 | int n, sqt, nsqt;
16 | vector p, s;
17 | vector > b;
18 | vector child;
19 |
20 | node(T *ini, int n_)
21 | {
22 | v = ini;
23 | n = n_;
24 | sqt = sqrt(n);
25 | nsqt = n/sqt + (n%sqt == 0? 0: 1);
26 | p.resize(n);
27 | s.resize(n);
28 | b.resize(nsqt);
29 |
30 | build_p();
31 | build_s();
32 | build_b();
33 | if (n > 1) build_child();
34 | }
35 |
36 | void build_p()
37 | {
38 | for (int i = 0; i < n; i++) {
39 |
40 | if (i == 0 or i/sqt != (i-1)/sqt)
41 | p[i] = v[i];
42 | else
43 | p[i] = operation(p[i-1], v[i]);
44 | }
45 | }
46 |
47 | void build_s()
48 | {
49 | for (int i = n-1; i >= 0; i--) {
50 |
51 | if (i == n-1 or i/sqt != (i+1)/sqt)
52 | s[i] = v[i];
53 | else
54 | s[i] = operation(s[i+1], v[i]);
55 | }
56 | }
57 |
58 | void build_b()
59 | {
60 | for (int i = 0; i < nsqt; i++) {
61 |
62 | int fim = min(n-1, sqt*(i+1)-1);
63 | b[i].resize(nsqt);
64 | b[i][i] = p[fim];
65 |
66 | for (int j = i+1; j < nsqt; j++) {
67 |
68 | int at = min(n-1, sqt*(j+1)-1);
69 | b[i][j] = operation(b[i][j-1], p[at]);
70 | }
71 | }
72 | }
73 |
74 | void build_child()
75 | {
76 | child.resize(nsqt);
77 | for (int i = 0; i < nsqt; i++) {
78 |
79 | int ini = i*sqt;
80 | int fim = min(n-1, sqt*(i+1)-1);
81 | int se = fim-ini+1;
82 |
83 | child[i] = new node(v+ini, se);
84 | }
85 | }
86 |
87 | T query(int l, int r)
88 | {l
89 | if (l == r) return v[l];l
90 | if (l/sqt != r/sqt) return get(l, r);
91 |
92 | int block = l/sqt;
93 | int ini = block*sqt;
94 |
95 | return child[block]->query(l-ini, r-ini);
96 | }
97 |
98 | T get(int l, int r)
99 | {
100 | int lb = l/sqt + 1;
101 | int rb = r/sqt - 1;
102 |
103 | if (lb == rb+1) return operation(s[l], p[r]);
104 |
105 | return operation(b[lb][rb], operation(s[l], p[r]));
106 | }
107 | };
108 |
109 | const int maxn = 1000000;
110 |
111 | int v[maxn];
112 | int ans[maxn];
113 |
114 | int main()
115 | {
116 | for (int i = 0; i < maxn; i++) v[i] = rand();
117 |
118 | node *t = new node(v, maxn);
119 |
120 | mt19937 rd;
121 | uniform_int_distribution rnd(0, maxn-1);
122 |
123 | int q = maxn;
124 |
125 | while (q--) {
126 |
127 | int l = rnd(rd);
128 | int r = rnd(rd);
129 |
130 | if (l > r) swap(l, r);
131 |
132 | ans[q] = t->query(l, r);
133 | }
134 | }
--------------------------------------------------------------------------------
/data_structures/treap.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | template
6 | class Treap {
7 | private:
8 | struct Node
9 | {
10 | T val;
11 | int h, sz;
12 | Node *l, *r;
13 |
14 | Node(T x)
15 | : val(x), h(rand()), sz(1), l(nullptr), r(nullptr) {};
16 |
17 | friend ostream& operator<<(ostream& out, Node const& t)
18 | {
19 | if (t.l) out << *t.l;
20 | out << t.val << " ";
21 | if (t.r) out << *t.r;
22 | return out;
23 | }
24 | };
25 |
26 | void op(Node *t)
27 | {
28 | if (!t) return;
29 | t->sz = 1;
30 | if (t->l) t->sz += t->l->sz;
31 | if (t->r) t->sz += t->r->sz;
32 | }
33 |
34 | void merge(Node *&t, Node *l, Node *r)
35 | {
36 | if (!l or !r)
37 | return void(t=l?l:r);
38 | if (l->h > r->h)
39 | merge(l->r, l->r, r), t = l;
40 | else
41 | merge(r->l, l, r->l), t = r;
42 | op(t);
43 | }
44 |
45 | void split(Node *t, Node *&l, Node *&r, T v)
46 | {
47 | if (!t) return void(l=r=nullptr);
48 | if (v > t->val)
49 | split(t->r, t->r, r, v), l = t;
50 | else
51 | split(t->l, l, t->l, v), r = t;
52 | op(l), op(r);
53 | }
54 |
55 | void insert(Node *&t, Node *v)
56 | {
57 | if (!t) return void(t=v);
58 | if (v->h > t->h) split(t, v->l, v->r, v->val), t = v;
59 | else if (t->val <= v->val) insert(t->r, v);
60 | else insert(t->l, v);
61 | op(t);
62 | }
63 |
64 | void erase(Node *&t, T v)
65 | {
66 | if (!t) return;
67 | if (t->val == v) {
68 | Node *aux = t;
69 | merge(t, t->l, t->r);
70 | delete aux;
71 | }
72 | else if (t->val < v) erase(t->r, v);
73 | else erase(t->l, v);
74 | op(t);
75 | }
76 |
77 | T kth(Node *t, int pos)
78 | {
79 | int p = 1;
80 | if (t->l) p += t->l->sz;
81 |
82 | if (p == pos) return t->val;
83 | if (pos > p) return kth(t->r, pos-p);
84 | else return kth(t->l, pos);
85 | }
86 |
87 | int ord(Node *t, T val)
88 | {
89 | Node *aux = nullptr, *r = nullptr;
90 | split(root, aux, r, val);
91 |
92 | int ans = 0;
93 | if (aux) ans = aux->sz;
94 |
95 | merge(root, aux, r);
96 | return ans;
97 | }
98 |
99 | void del(Node *t)
100 | {
101 | if (t->l) del(t->l);
102 | if (t->r) del(t->r);
103 | delete t;
104 | }
105 |
106 | Node *root;
107 |
108 | public:
109 | void insert(T val)
110 | {
111 | Node *aux = new Node(val);
112 | insert(root, aux);
113 | }
114 |
115 | template
116 | void insert(T val, Args... args)
117 | {
118 | insert(val);
119 | insert(args...);
120 | }
121 |
122 | void erase(T val)
123 | {
124 | erase(root, val);
125 | }
126 |
127 | template
128 | void erase(T val, Args... args)
129 | {
130 | erase(val);
131 | erase(args...);
132 | }
133 |
134 | void erase_range(T ini, T fim)
135 | {
136 | Node *l = nullptr, *r = nullptr, *aux=nullptr;
137 | split(root, l, aux, ini);
138 | split(aux, aux, r, fim);
139 | del(aux);
140 | merge(root, l, r);
141 | }
142 |
143 | T kth(int pos)
144 | {
145 | return kth(root, pos+1);
146 | }
147 |
148 | int ord(T val)
149 | {
150 | return ord(root, val);
151 | }
152 |
153 | friend ostream& operator<<(ostream& out, Treap const& tp)
154 | {
155 | if (!tp.root) return out;
156 | out << *tp.root;
157 | return out;
158 | }
159 |
160 | Treap()
161 | {
162 | root = nullptr;
163 | }
164 |
165 | ~Treap()
166 | {
167 | if (root) del(root);
168 | }
169 | };
170 |
171 | int main()
172 | {
173 | Treap tp;
174 |
175 | tp.insert(3, 1, 5);
176 | cout << tp << "\n";
177 |
178 | tp.erase(3);
179 | cout << tp << "\n";
180 |
181 | tp.insert(2, 3, 4);
182 | cout << tp << "\n";
183 |
184 | cout << tp.kth(4) << "\n";
185 | cout << tp.ord(5) << "\n";
186 |
187 | tp.erase_range(2, 5);
188 | cout << tp << "\n";
189 | }
--------------------------------------------------------------------------------
/data_structures/treap_build.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "/home/fred/test_cases/jng.h"
3 |
4 | using namespace std;
5 |
6 | typedef unsigned int ui;
7 |
8 | const int maxn = 10101010;
9 |
10 | struct node
11 | {
12 | int val;
13 | int h, sz;
14 |
15 | node *l, *r;
16 |
17 | node(int val)
18 | : val(val), h(rand()), sz(1), l(nullptr), r(nullptr) {};
19 | node(int val, int sz)
20 | : val(val), h(0), sz(sz), l(nullptr), r(nullptr) {};
21 |
22 | };
23 |
24 | int v[maxn];
25 |
26 | node* build(int l, int r)
27 | {
28 | if (l == r) return new node(v[l], 1);
29 | if (l > r) return nullptr;
30 |
31 | int m = (l+r)>>1;
32 |
33 | node *at = new node(v[m], r-l+1);
34 |
35 | at->l = build(l, m-1);
36 | at->r = build(m+1, r);
37 |
38 | return at;
39 | }
40 |
41 | int s = 0;
42 |
43 | void fix(int n, node *no)
44 | {
45 | queue q;
46 | q.push(no);
47 |
48 | int step = (ui(-1))/(n+1);
49 |
50 | int at = 0x7fffffff;
51 | at -= step;
52 |
53 | while (!q.empty()) {
54 |
55 | node *t = q.front();
56 | q.pop();
57 |
58 | t->h = at;
59 | at -= step;
60 |
61 | if (t->l) q.push(t->l);
62 | if (t->r) q.push(t->r);
63 | }
64 | }
65 |
66 | ostream& operator<<(ostream& out, node *t)
67 | {
68 | if (!t) return out;
69 |
70 | out << t->l << t->val << " "<< t->r;
71 |
72 | return out;
73 | }
74 |
75 | int main()
76 | {
77 | ios_base::sync_with_stdio(false), cin.tie(0);
78 |
79 | int n;
80 | cin >> n;
81 |
82 | for (int i = 0; i < n; i++) cin >> v[i];
83 |
84 | auto timer = new ContextTimer("build");
85 |
86 | sort(v, v+n);
87 |
88 | node *t = build(0, n-1);
89 |
90 | fix(n, t);
91 |
92 | delete timer;
93 |
94 | cout << t->val << "\n";
95 | }
--------------------------------------------------------------------------------
/data_structures/treap_impl.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | mt19937 rd{17};
6 |
7 | template
8 | class Treap {
9 | private:
10 | struct Node {
11 | Node *l, *r;
12 | T val;
13 | uint32_t h, sz;
14 |
15 | Node() = default;
16 |
17 | ~Node() {};
18 |
19 | Node(T const& x)
20 | : l(nullptr), r(nullptr), val(x), h(rd()), sz(1) {};
21 |
22 | friend ostream& operator<<(ostream& out, Node const& t)
23 | {
24 | if (t.l) out << *t.l;
25 | out << t.val << " ";
26 | if (t.r) out << *t.r;
27 | return out;
28 | }
29 | };
30 |
31 |
32 | void op(Node *t) {
33 | if (!t) return;
34 | t->sz = 1;
35 | if (t->l) t->sz += t->l->sz;
36 | if (t->r) t->sz += t->r->sz;
37 | }
38 |
39 | void merge(Node *&t, Node *l, Node *r) {
40 | if (!l or !r)
41 | return void(t=l?l:r);
42 | if (l->h > r->h)
43 | merge(l->r, l->r, r), t = l;
44 | else
45 | merge(r->l, l, r->l), t = r;
46 | op(t);
47 | }
48 |
49 | void split(Node *t, Node *&l, Node *&r, int pos) {
50 | if (!t) return void(l=r=nullptr);
51 |
52 | int p = 1;
53 | if (t->l) p += t->l->sz;
54 |
55 | if (p < pos)
56 | split(t->r, t->r, r, pos-p), l = t;
57 | else
58 | split(t->l, l, t->l, pos), r = t;
59 | op(l), op(r);
60 | }
61 |
62 | void insert(Node *&t, Node *aux, int pos) {
63 | if (!t) {
64 | t = aux;
65 | op(t);
66 | return;
67 | }
68 |
69 | int p = 1;
70 | if (t->l) p += t->l->sz;
71 |
72 | if (t->h < aux->h) split(t, aux->l, aux->r, pos), t = aux;
73 | else if (p >= pos) insert(t->l, aux, pos);
74 | else insert(t->r, aux, pos-p);
75 |
76 | op(t);
77 | }
78 |
79 | void erase(Node *&t, int pos) {
80 | if (!t) return;
81 |
82 | int p = 1;
83 | if (t->l) p += t->l->sz;
84 |
85 | if (p == pos) merge(t, t->l, t->r);
86 | else if (p < pos) erase(t->r, pos-p);
87 | else erase(t->l, pos);
88 |
89 | op(t);
90 | }
91 |
92 | Node& kth(Node *t, int pos)
93 | {
94 | int p = 1;
95 | if (t->l) p += t->l->sz;
96 |
97 | if (p == pos) return *t;
98 | if (pos > p) return kth(t->r, pos-p);
99 | else return kth(t->l, pos);
100 | }
101 |
102 | Node *root = nullptr;
103 | vector aux_new;
104 | int idx = 0;
105 |
106 | Node* _get_ptr(T const& val) {
107 | return ::new (static_cast(&aux_new[idx++])) Node(val);
108 | }
109 |
110 | public:
111 | class Iterator {
112 | public:
113 | stack bt;
114 | Iterator() = default;
115 | Iterator(Iterator&& t) : bt(move(t.bt)) {};
116 | Iterator(Iterator const& t) : bt(t.bt) {};
117 |
118 | Iterator& operator=(Iterator&& t) {
119 | return Iterator(move(t));
120 | }
121 |
122 | Iterator& operator=(Iterator const& t) {
123 | return Iterator(t);
124 | }
125 |
126 | Iterator& operator++() {
127 | Node* t = bt.top();
128 |
129 | if (!t->r) {
130 | bt.pop();
131 | return *this;
132 | }
133 |
134 | t = t->r;
135 | bt.pop();
136 | bt.push(t);
137 |
138 | while (t->l) {
139 | t = t->l;
140 | bt.push(t);
141 | }
142 |
143 | return *this;
144 | }
145 |
146 | Node& operator*() {
147 | return *bt.top();
148 | }
149 |
150 | Node* operator->() {
151 | return bt.top();
152 | }
153 |
154 | bool operator==(Iterator const& t) const {
155 | return bt == t.bt;
156 | }
157 |
158 | bool operator!=(Iterator const& t) const {
159 | return !(bt == t.bt);
160 | }
161 | };
162 |
163 | Iterator begin() {
164 | Iterator it;
165 | Node* t = root;
166 |
167 | while (t and t->l) {
168 | it.bt.push(t);
169 | t = t->l;
170 | }
171 | if (t) it.bt.push(t);
172 |
173 | return it;
174 | }
175 |
176 | Iterator end() {
177 | return Iterator();
178 | }
179 |
180 | void insert(int pos, T const& val)
181 | {
182 | Node *l = nullptr, *r = nullptr, *aux = _get_ptr(val);
183 | insert(root, aux, pos+1);
184 | }
185 |
186 | void erase(int pos)
187 | {
188 | erase(root, pos+1);
189 | }
190 |
191 | Node& kth(int pos)
192 | {
193 | return kth(root, pos+1);
194 | }
195 |
196 | friend ostream& operator<<(ostream& out, Treap const& tp)
197 | {
198 | if (!tp.root) return out;
199 | out << *tp.root;
200 | return out;
201 | }
202 |
203 | Treap()
204 | {
205 | aux_new.resize(1'000'000);
206 | root = nullptr;
207 | }
208 | };
209 |
210 | class Timer {
211 | public:
212 | Timer(const std::string& name) : name_(name) {
213 | start_ = std::chrono::steady_clock::now();
214 | }
215 |
216 | Timer() : Timer("") {}
217 |
218 | Timer(const Timer&) = delete;
219 | Timer& operator=(const Timer&) = delete;
220 | Timer(Timer&&) = delete;
221 | Timer& operator=(Timer&&) = delete;
222 |
223 | ~Timer() {
224 | auto dif = std::chrono::steady_clock::now() - start_;
225 | auto ms = std::chrono::duration_cast(dif);
226 | if (!name_.empty()) {
227 | std::cerr << "[" << name_ << "] ";
228 | }
229 | std::cerr << ms.count() << " ms\n";
230 | }
231 |
232 | private:
233 | std::string name_;
234 | std::chrono::steady_clock::time_point start_;
235 | };
236 |
237 | struct Query {
238 | enum class Op{
239 | INSERT,
240 | ERASE,
241 | QUERY,
242 | } opt;
243 | // Op opt;
244 | int pos, val;
245 | };
246 |
247 | vector gen_bench(int n, int p_insert, int p_erase, int p_query) {
248 | vector v(n);
249 |
250 | mt19937 rg{13};
251 |
252 | uniform_int_distribution roll(0, 99);
253 |
254 | int num = 0;
255 |
256 | auto f = [&num, p_insert, p_erase, p_query] (int p) {
257 | if (num == 0 or p < p_insert) {
258 | num++;
259 | return Query::Op::INSERT;
260 | }
261 | else if (p < p_insert+p_erase) {
262 | num--;
263 | return Query::Op::ERASE;
264 | }
265 | else return Query::Op::QUERY;
266 | };
267 |
268 | for (auto& qr : v) {
269 | int p = roll(rg);
270 |
271 | int pos = uniform_int_distribution(0, num)(rg);
272 | int val = rg();
273 | qr = {f(p), pos, val};
274 | }
275 |
276 | return v;
277 | }
278 |
279 | int64_t run_bench(vector const& qrs, Treap& tp) {
280 | Timer timer{"total"};
281 | int64_t total = 0;
282 | for (auto const& qr : qrs) {
283 | if (qr.opt == Query::Op::INSERT) tp.insert(qr.pos, qr.val);
284 | else if (qr.opt == Query::Op::ERASE) tp.erase(qr.pos);
285 | else total += tp.kth(qr.pos).val;
286 | }
287 | return total;
288 | }
289 |
290 | int main()
291 | {
292 | Treap tp;
293 |
294 | tp.insert(0,3);
295 | tp.insert(1,1);
296 | tp.insert(2,2);
297 | tp.insert(3,5);
298 | tp.insert(4,7);
299 | tp.insert(5,6);
300 |
301 | for (auto it : tp) cout << it.val << "\n";
302 |
303 | auto ans = run_bench(gen_bench(1'000'000, 60, 20, 20), tp);
304 |
305 | cout << ans << "\n";
306 | }
--------------------------------------------------------------------------------
/data_structures/trie.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | class Trie {
6 | private:
7 | struct Node
8 | {
9 | Node* b[26];
10 | bool fim = false;
11 | };
12 |
13 | Node* root;
14 |
15 | void add(Node* rt, string const& s)
16 | {
17 | Node *at = rt;
18 |
19 | for (char a : s) {
20 | if (!at->b[a-'a'])
21 | at->b[a-'a'] = new Node();
22 | at = at->b[a-'a'];
23 | }
24 | at->fim = true;
25 | }
26 |
27 | bool find(Node* rt, string const& s)
28 | {
29 | Node *at = rt;
30 |
31 | for (char a : s) {
32 | if (!at->b[a-'a'])
33 | return false;
34 | at = at->b[a-'a'];
35 | }
36 | return at->fim;
37 | }
38 | public:
39 | void insert(string const& s)
40 | {
41 | add(root, s);
42 | }
43 |
44 | bool find(string const& s)
45 | {
46 | return find(root, s);
47 | }
48 |
49 | Trie()
50 | {
51 | root = new Node();
52 | }
53 | };
54 |
55 | int main()
56 | {
57 | Trie tr;
58 |
59 | tr.insert("teste");
60 |
61 | cout << boolalpha << tr.find("test") << "\n";
62 | cout << boolalpha << tr.find("teste") << "\n";
63 | }
--------------------------------------------------------------------------------
/data_structures/trie_xor.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | class Trie {
6 | private:
7 | struct Node
8 | {
9 | Node* b[2];
10 | };
11 |
12 | Node* root;
13 |
14 | void add(Node* rt, int s)
15 | {
16 | Node *at = rt;
17 |
18 | for (int idx = 30; idx >= 0; idx--) {
19 | int now = (s&(1<b[now])
22 | at->b[now] = new Node();
23 | at = at->b[now];
24 | }
25 | }
26 |
27 | int find(Node* rt, int s)
28 | {
29 | Node *at = rt;
30 |
31 | int ans = 0;
32 | for (int idx = 30; idx >= 0; idx--) {
33 | int now = (s&(1<b[now])
36 | ans |= (now<b[now];
37 | else
38 | ans |= ((1-now)<b[1-now];
39 | }
40 | return ans;
41 | }
42 | public:
43 | void insert(int s)
44 | {
45 | add(root, s);
46 | }
47 |
48 | int find(int s)
49 | {
50 | return find(root, s);
51 | }
52 |
53 | Trie()
54 | {
55 | root = new Node();
56 | }
57 | };
58 |
59 | int main()
60 | {
61 | Trie tr;
62 |
63 | tr.insert(3);
64 | tr.insert(5);
65 |
66 | cout << tr.find(2) << "\n";
67 | }
--------------------------------------------------------------------------------
/data_structures/wavelet.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | typedef vector vi;
6 |
7 | const int maxn = 100100;
8 | const int maxm = 1000000000;
9 |
10 | int v[maxn];
11 |
12 | struct wtree
13 | {
14 | int lo, hi;
15 | wtree *l, *r;
16 | vi b;
17 |
18 | wtree(int *from, int *to, int x, int y)
19 | {
20 | lo = x, hi = y;
21 |
22 | if (lo == hi or from >= to) return;
23 |
24 | int mid = (lo+hi)/2;
25 |
26 | auto f = [&](int x) -> bool
27 | {
28 | return x <= mid;
29 | };
30 |
31 | b.reserve(to-from+1);
32 | b.push_back(0);
33 |
34 | for (auto it = from; it != to; it++) {
35 |
36 | b.push_back(b.back() + f(*it));
37 | }
38 |
39 | auto pivot = stable_partition(from, to, f);
40 |
41 | l = new wtree(from, pivot, lo, mid);
42 | r = new wtree(pivot, to, mid+1, hi);
43 | }
44 |
45 | // kth element between l and r
46 | int kth(int l, int r, int k)
47 | {
48 | if (l > r) return 0;
49 | if (lo == hi) return lo;
50 |
51 | int inleft = b[r] - b[l-1];
52 |
53 | int lb = b[l-1];
54 | int rb = b[r];
55 |
56 | if (k <= inleft) return this->l->kth(lb+1, rb, k);
57 | return this->r->kth(l-lb, r-rb, k-inleft);
58 | }
59 |
60 | // number of elements between l and r less or equal than k
61 | int lte(int l, int r, int k)
62 | {
63 | if (l > r or k < lo or k > hi) return 0;
64 |
65 | if (hi <= k) return r-l+1;
66 |
67 | int lb = b[l-1], rb = b[r];
68 |
69 | return this->l->lte(lb+1, rb, k) + this->r->lte(l-lb, r-rb, k);
70 | }
71 |
72 | // number of elements between l and r equal to k
73 | int count(int l, int r, int k)
74 | {
75 | if (l > r or k < lo or k > r) return 0;
76 |
77 | if (lo == hi) return r-l+1;
78 |
79 | int lb = b[l-1], rb = b[r], mid = (l+r)/2;
80 |
81 | if (k <= mid) return this->l->count(lb+1, rb, k);
82 | return this->r->count(l-lb, r-rb, k);
83 | }
84 |
85 | ~wtree()
86 | {
87 | delete l;
88 | delete r;
89 | }
90 | };
91 |
92 | int main()
93 | {
94 | ios_base::sync_with_stdio(false);
95 | // cin.tie(0);
96 |
97 | int n;
98 | cin >> n;
99 |
100 | for (int i = 1; i <= n; i++) cin >> v[i];
101 |
102 | wtree *t = new wtree(v+1, v+n+1, 1, maxm);
103 |
104 | int q;
105 | cin >> q;
106 |
107 | while (q--) {
108 |
109 | int l, r, k;
110 | cin >> l >> r >> k;
111 |
112 | int res = t->kth(l, r, k);
113 |
114 | cout << res << "\n";
115 | }
116 |
117 | return 0;
118 | }
--------------------------------------------------------------------------------
/data_structures/wavelet_static.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define LEFT ((no*2)+1)
4 | #define RIGHT ((no*2)+2)
5 |
6 | using namespace std;
7 |
8 | typedef vector vi;
9 |
10 | const int maxn = 100010;
11 | const int maxm = maxn;
12 |
13 | int v[maxn];
14 | vi b[maxn*4];
15 | int mid;
16 |
17 | inline bool f(int x)
18 | {
19 | return x <= mid;
20 | }
21 |
22 | void build(int no, int *from, int *to, int lo, int hi)
23 | {
24 | if (from >= to or lo == hi) return;
25 |
26 | mid = (lo+hi)/2;
27 |
28 | b[no].push_back(0);
29 |
30 | for (int *it = from; it != to; it++) {
31 |
32 | b[no].push_back(b[no].back() + f(*it));
33 | }
34 |
35 | int *pivot = stable_partition(from, to, f);
36 |
37 | build(LEFT, from, pivot, lo, mid);
38 | mid = (lo+hi)/2;
39 | build(RIGHT, pivot, to, mid+1, hi);
40 | }
41 |
42 | int kth(int no, int lo, int hi, int l, int r, int k)
43 | {
44 | if (l > r) return 0;
45 |
46 | if (lo == hi) return lo;
47 |
48 | mid = (lo+hi)/2;
49 |
50 | int lb = b[no][l-1];
51 | int rb = b[no][r];
52 | int inleft = rb - lb;
53 |
54 | if (inleft >= k) return kth(LEFT, lo, mid, lb+1, rb, k);
55 | return kth(RIGHT, mid+1, hi, l-lb, r-rb, k-inleft);
56 | }
57 |
58 | int main()
59 | {
60 | int n, q;
61 | cin >> n >> q;
62 |
63 | for (int i = 1; i <= n; i++) cin >> v[i];
64 |
65 | build(0, v+1, v+1+n, 1, maxm);
66 |
67 | while (q--) {
68 |
69 | int l, r, k;
70 | cin >> l >> r >> k;
71 |
72 | int res = kth(0, 1, maxm, l, r, k);
73 |
74 | cout << res << "\n";
75 | }
76 |
77 | return 0;
78 | }
--------------------------------------------------------------------------------
/dynamic_programming/divide_and_conquer.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | int const maxn = 101010;
6 | int const maxk = 11;
7 | int const inf = 0x3f3f3f3f;
8 |
9 | int v[maxn], pref[maxn];
10 | int dp[maxk][maxn];
11 |
12 | int f(int i, int j) {
13 | return (pref[j]-pref[i-1]) * (j-i+1);
14 | }
15 |
16 | void solve(int k, int l, int r, int optl, int optr)
17 | {
18 | if (l > r) return;
19 |
20 | int m = (l+r)/2;
21 |
22 | dp[k][m] = inf;
23 | int opt = m;
24 |
25 | int cost = 0;
26 | for (int i = m-1; i > optr; i--) cost += f(i, m);
27 |
28 | for (int i = min(optr, m); i >= optl; i--) {
29 | cost += f(i, m);
30 | if (cost + dp[k-1][i-1] < dp[k][m]) {
31 | dp[k][m] = cost + dp[k-1][i-1];
32 | opt = i;
33 | }
34 | }
35 |
36 | solve(k, l, m-1, optl, opt);
37 | solve(k, m+1, r, opt, optr);
38 | }
39 |
40 | int main()
41 | {
42 |
43 | }
--------------------------------------------------------------------------------
/dynamic_programming/knapsack_01.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 1010;
6 | const int maxm = 101010;
7 |
8 | int w[maxn], c[maxn];
9 | int d[maxm];
10 |
11 | int main()
12 | {
13 | int n, m;
14 | cin >> n >> m;
15 |
16 | for (int i = 1; i <= n; i++)
17 | cin >> w[i] >> c[i];
18 |
19 | memset(d, -1, sizeof(d));
20 | d[0] = 0;
21 |
22 | for (int i = 1; i <= n; i++)
23 | for (int j = m; j >= w[i]; j--)
24 | if (d[j-w[i]] >= 0)
25 | d[j] = max(d[j], d[j-w[i]]+c[i]);
26 |
27 | int ans = 0;
28 | for (int i = 0; i <= m; i++)
29 | ans = max(ans, d[i]);
30 |
31 | cout << ans << "\n";
32 | }
--------------------------------------------------------------------------------
/dynamic_programming/knapsack_bitset.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace std;
5 |
6 | int const maxn = 101;
7 | int const maxm = 100000001;
8 |
9 | int v[maxn];
10 | // must to have two bitsets as one serves as temporary to avoid
11 | // stack oveflow which happens when large bitsets are implicitly
12 | // allocated eg. dp |= dp< dp, dp2;
14 |
15 | // find first value > m that cannot be formed by the sums of
16 | // numbers from v
17 | int main()
18 | {
19 | int n, m;
20 | cin >> n >> m;
21 |
22 | for (int i = 0; i < n; i++) cin >> v[i];
23 |
24 | dp[0] = true;
25 | dp2[0] = true;
26 | for (int i = 0; i < n; i++) {
27 | dp2 <<= v[i];
28 | dp |= dp2;
29 | dp2 = dp;
30 | }
31 |
32 | dp.flip();
33 | cout << dp._Find_next(m) << "\n";
34 | }
35 |
--------------------------------------------------------------------------------
/dynamic_programming/knapsack_bounded.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define ff first
4 | #define ss second
5 |
6 | using namespace std;
7 |
8 | typedef pair ii;
9 |
10 | struct minqueue
11 | {
12 | deque dq;
13 |
14 | int l, r, sum;
15 |
16 | void clear()
17 | {
18 | l = r = sum = 0;
19 | dq.clear();
20 | }
21 |
22 | void push(int x)
23 | {
24 | while (!dq.empty() and dq.back().ff > x-sum) dq.pop_back();
25 | dq.push_back({x-sum,r});
26 | r++;
27 | }
28 |
29 | void pop()
30 | {
31 | if (!dq.empty() and dq.front().ss == l) dq.pop_front();
32 | l++;
33 | }
34 |
35 | void add(int x) {sum += x;}
36 |
37 | int getmin() {return dq[0].ff+sum;}
38 |
39 | int size() {return r-l;}
40 | };
41 |
42 | const int maxn = 1000;
43 | const int maxm = 100000;
44 | const int inf = 0x3f3f3f;
45 |
46 | minqueue q[maxm];
47 |
48 | int d[maxm];
49 | int w[maxn], e[maxn], c[maxn];
50 |
51 | int main()
52 | {
53 | int n, m;
54 | cin >> n >> m;
55 |
56 | for (int i = 1; i <= n; i++) cin >> w[i] >> e[i] >> c[i];
57 |
58 | for (int i = 1; i <= m; i++) d[i] = inf;
59 |
60 | for (int i = 1; i <= n; i++) {
61 |
62 | for (int j = 0; j < w[i]; j++) q[j].clear();
63 |
64 | for (int j = 0; j <= m; j++) {
65 |
66 | minqueue& mq = q[j%w[i]];
67 |
68 | if (mq.size() > e[i]) mq.pop();
69 |
70 | mq.add(c[i]);
71 | mq.push(d[j]);
72 |
73 | d[j] = mq.getmin();
74 | }
75 | }
76 |
77 | for (int i = 0; i <= m; i++) cout << d[i] << " ";
78 | cout << "\n";
79 | }
--------------------------------------------------------------------------------
/dynamic_programming/knapsack_unbounded.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 1010;
6 | const int maxm = 101010;
7 |
8 | int w[maxn], c[maxn];
9 | int d[maxm];
10 |
11 | int main()
12 | {
13 | int n, m;
14 | cin >> n >> m;
15 |
16 | for (int i = 1; i <= n; i++)
17 | cin >> w[i] >> c[i];
18 |
19 | memset(d, -1, sizeof(d));
20 | d[0] = 0;
21 |
22 | for (int i = 1; i <= m; i++)
23 | for (int j = 1; j <= n; j++)
24 | if (w[j] <= i and d[i-w[j]] >= 0)
25 | d[i] = max(d[i], d[i-w[j]] + c[j]);
26 |
27 | int ans = 0;
28 | for (int i = 0; i <= m; i++)
29 | ans = max(ans, d[i]);
30 |
31 | cout << ans << "\n";
32 | }
--------------------------------------------------------------------------------
/dynamic_programming/lcs.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 1010;
6 |
7 | int n, m;
8 |
9 | int a[maxn], b[maxn];
10 | int dp[maxn][maxn];
11 |
12 | int solve(int i, int j)
13 | {
14 | if (i > n or j > m) return 0;
15 | if (dp[i][j] >= 0) return dp[i][j];
16 |
17 | if (a[i] == b[j]) return dp[i][j] = 1 + solve(i+1, j+1);
18 |
19 | return dp[i][j] = max(solve(i+1, j), solve(i, j+1));
20 | }
21 |
22 | int d[2][maxn];
23 |
24 | int main()
25 | {
26 | memset(dp, -1, sizeof(dp));
27 |
28 | cin >> n >> m;
29 |
30 | for (int i = 1; i <= n; i++)
31 | cin >> a[i];
32 | for (int i = 1; i <= m; i++)
33 | cin >> b[i];
34 |
35 | int ans = solve(1, 1);
36 | cout << ans << "\n";
37 |
38 | int now = 0, old = 1;
39 |
40 | for (int i = n; i >= 1; --i) {
41 | swap(now, old);
42 | for (int j = m; j >= 1; --j) {
43 | if (a[i] == b[j]) d[now][j] = 1 + d[old][j+1];
44 | else d[now][j] = max(d[old][j],
45 | d[now][j+1]);
46 | }
47 | }
48 |
49 | cout << d[now][1] << "\n";
50 | }
--------------------------------------------------------------------------------
/dynamic_programming/lis.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | template
6 | struct Bit
7 | {
8 | int b[sz];
9 |
10 | void upd(int x, int val)
11 | {
12 | for (int i = x; i < sz; i += i&-i)
13 | b[i] = max(b[i], val);
14 | }
15 |
16 | int get(int x)
17 | {
18 | int ans = 0;
19 | for (int i = x; i; i -= i&-i)
20 | ans = max(ans, b[i]);
21 | return ans;
22 | }
23 | };
24 |
25 | template
26 | void compress(T* v, int n)
27 | {
28 | vector vv(n+1);
29 | for (int i = 1; i <= n; i++)
30 | vv[i] = v[i];
31 |
32 | sort(vv.begin()+1, vv.end());
33 |
34 | for (int i = 1; i <= n; i++)
35 | v[i] = lower_bound(vv.begin()+1, vv.end(), v[i]) - vv.begin();
36 | }
37 |
38 | const int maxn = 101010;
39 |
40 | int v[maxn];
41 | Bit bt;
42 |
43 | int main()
44 | {
45 | int n;
46 | cin >> n;
47 |
48 | for (int i = 1; i <= n; i++)
49 | cin >> v[i];
50 |
51 | compress(v, n);
52 |
53 | for (int i = 1; i <= n; i++) {
54 | int x = bt.get(v[i]-1);
55 | bt.upd(v[i], x+1);
56 | }
57 |
58 | int ans = bt.get(n);
59 |
60 | cout << ans << "\n";
61 | }
--------------------------------------------------------------------------------
/dynamic_programming/subset_sums.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | using ll = long long;
6 |
7 | vector all_sums(vector const& v)
8 | {
9 | vector ans(1<> n >> a >> b;
32 |
33 | vector v(n);
34 | for (int i = 0; i < n; i++) cin >> v[i];
35 |
36 | int mid = n/2;
37 | vector v1(v.begin(), v.begin()+mid);
38 | vector v2(v.begin()+mid, v.end());
39 |
40 | auto s1 = all_sums(v1), s2 = all_sums(v2);
41 |
42 | reverse(s1.begin(), s1.end());
43 |
44 | ll ans = 0;
45 | auto l = s2.begin(), r = s2.begin();
46 | for (ll i : s1) {
47 | // amount of numbers in range [a, b]
48 | // using two-pointers technique
49 | while (r != s2.end() and *r+i <= b) ++r;
50 | while (l != s2.end() and *l+i < a) ++l;
51 | ans += r-l;
52 |
53 | }
54 |
55 | // overall complexity O(2^(n/2)) ~ O(1.41^n)
56 | cout << ans << "\n";
57 | }
--------------------------------------------------------------------------------
/etc/bitset_extra.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | int main()
6 | {
7 | bitset<100> bt;
8 | cin >> bt;
9 |
10 | cout << bt[0] << "\n";
11 | cout << bt.count() << "\n";
12 | cout << (~bt).none() << "\n";
13 | cout << (~bt).any() << "\n";
14 | cout << (~bt).all() << "\n";
15 | cout << bt._Find_first() << "\n";
16 | cout << bt._Find_next(10) << "\n";
17 |
18 | cout << bt << "\n";
19 | }
--------------------------------------------------------------------------------
/etc/compression.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | // compresses values in positions [ini, fim) to [pos, n+pos]
6 | template
7 | void compress(Iter ini, Iter fim, int pos=1)
8 | {
9 | using T = typename decay::type;
10 |
11 | vector vv(ini, fim);
12 | sort(vv.begin(), vv.end());
13 | vv.erase(unique(vv.begin(), vv.end()), vv.end());
14 |
15 | for_each(ini, fim, [&] (T& x) {
16 | x = lower_bound(vv.begin(), vv.end(), x) - vv.begin() + pos;
17 | });
18 | }
19 |
20 | int va[] = {0, 1000, 2000, 5000, 3000};
21 | vector v{1000, 2000, 5000, 3000};
22 |
23 | int main()
24 | {
25 | compress(va+1, va+5);
26 | compress(v.begin(), v.end(), 0);
27 |
28 | for (int i = 1; i <= 4; i++)
29 | cout << va[i] << " ";
30 | cout << "\n";
31 |
32 | for (int i : v) cout << i << " ";
33 | cout << "\n";
34 | }
35 |
--------------------------------------------------------------------------------
/etc/fast_input.cpp:
--------------------------------------------------------------------------------
1 | inline int scan () {
2 | int result = 0;
3 | char ch;
4 | bool minus = false;
5 | ch = getchar_unlocked();
6 | while (true) {
7 | if (ch == '-') break;
8 | if (ch >= '0' && ch <= '9') break;
9 | ch = getchar_unlocked();
10 | }
11 | if (ch == '-') minus = true; else result = ch-'0';
12 | while (true) {
13 | ch = getchar_unlocked();
14 | if (ch < '0' || ch > '9') break;
15 | result = result*10 + (ch - '0');
16 | }
17 | if (minus) return -result;
18 | return result;
19 | }
20 |
21 |
22 | /*------------------------------------------*/
23 | /*-----------FUDEROSAMENTE RAPIDO-----------*/
24 | /*------------------------------------------*/
25 |
26 | inline int readChar();
27 | template inline T readInt();
28 | template inline void writeInt( T x, char end = 0 );
29 | inline void writeChar( int x );
30 | inline void writeWord( const char *s );
31 |
32 | /** Read */
33 |
34 | static const int buf_size = 4096;
35 |
36 | inline int getChar() {
37 | static char buf[buf_size];
38 | static int len = 0, pos = 0;
39 | if (pos == len)
40 | pos = 0, len = fread(buf, 1, buf_size, stdin);
41 | if (pos == len)
42 | return -1;
43 | return buf[pos++];
44 | }
45 |
46 | inline int readChar() {
47 | int c = getChar();
48 | while (c <= 32)
49 | c = getChar();
50 | return c;
51 | }
52 |
53 | template
54 | inline T readInt() {
55 | char c = readChar();
56 | T x = 0;
57 | while ('0' <= c && c <= '9')
58 | x = x * 10 + c - '0', c = getChar();
59 | return x;
60 | }
61 |
62 | /** Write */
63 |
64 | static int write_pos = 0;
65 | static char write_buf[buf_size];
66 |
67 | inline void writeChar( int x ) {
68 | if (write_pos == buf_size)
69 | fwrite(write_buf, 1, buf_size, stdout), write_pos = 0;
70 | write_buf[write_pos++] = x;
71 | }
72 |
73 | template
74 | inline void writeInt( T x, char end ) {
75 | if (x < 0)
76 | writeChar('-'), x = -x;
77 |
78 | char s[24];
79 | int n = 0;
80 | while (x || !n)
81 | s[n++] = '0' + x % 10, x /= 10;
82 | while (n--)
83 | writeChar(s[n]);
84 | if (end)
85 | writeChar(end);
86 | }
87 |
88 | inline void writeWord( const char *s ) {
89 | while (*s)
90 | writeChar(*s++);
91 | }
92 |
93 | struct Flusher {
94 | ~Flusher() {
95 | if (write_pos)
96 | fwrite(write_buf, 1, write_pos, stdout), write_pos = 0;
97 | }
98 | } flusher;
--------------------------------------------------------------------------------
/etc/seed_random.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | struct random_seeder
6 | {
7 | template
8 | void generate(T begin, T end) const
9 | {
10 | for (random_device r; begin != end; ++begin)
11 | *begin = r();
12 | }
13 | } sd;
14 |
15 | int main()
16 | {
17 | mt19937_64 rnd{sd};
18 |
19 | uniform_int_distribution rng(0, 255);
20 |
21 | for (int i = 0; i < 10; i++) cout << char(rng(rnd));
22 |
23 | return 0;
24 | }
--------------------------------------------------------------------------------
/geometry/convex_hull.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | typedef long long ll;
6 |
7 | template
8 | struct Point
9 | {
10 | T x, y;
11 |
12 | Point operator+(Point const& rhs) const
13 | {
14 | return {x+rhs.x, y+rhs.y};
15 | }
16 |
17 | Point operator-(Point const& rhs) const
18 | {
19 | return {x-rhs.x, y-rhs.y};
20 | }
21 |
22 | T operator*(Point const& rhs) const
23 | {
24 | return x*rhs.x + y*rhs.y;
25 | }
26 |
27 | T operator^(Point const& rhs) const
28 | {
29 | return x*rhs.y - y*rhs.x;
30 | }
31 |
32 | bool operator<(Point const& rhs) const
33 | {
34 | if (x == rhs.x) return y < rhs.y;
35 | return x < rhs.x;
36 | }
37 | };
38 |
39 | vector> points;
40 |
41 | int main()
42 | {
43 | int n;
44 | cin >> n;
45 |
46 | for (int i = 0; i < n; i++) {
47 | ll x, y;
48 | cin >> x >> y;
49 |
50 | points.push_back({x, y});
51 | }
52 |
53 | sort(points.begin(), points.end());
54 |
55 | vector> up, down;
56 |
57 | for (Point pt : points) {
58 | while (up.size() >= 2 and
59 | ((pt-up.back())^(*(up.end()-2)-up.back())) > 0)
60 | up.pop_back();
61 | while (down.size() >= 2 and
62 | ((pt-down.back())^(*(down.end()-2)-down.back())) < 0)
63 | down.pop_back();
64 | up.push_back(pt);
65 | down.push_back(pt);
66 | }
67 |
68 | cout << "Up hull\n";
69 | for (Point const& pt : up)
70 | cout << pt.x << " " << pt.y << "\n";
71 |
72 | cout << "Down hull\n";
73 | for (Point const& pt : down)
74 | cout << pt.x << " " << pt.y << "\n";
75 | }
76 |
--------------------------------------------------------------------------------
/geometry/point.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | typedef long long ll;
6 |
7 | template
8 | struct Point
9 | {
10 | T x, y;
11 |
12 | Point operator+(Point const& rhs)
13 | {
14 | return {x+rhs.x, y+rhs.y};
15 | }
16 |
17 | Point operator-(Point const& rhs)
18 | {
19 | return {x-rhs.x, y-rhs.y};
20 | }
21 |
22 | T operator*(Point const& rhs)
23 | {
24 | return x*rhs.x + y*rhs.y;
25 | }
26 |
27 | T operator^(Point const& rhs)
28 | {
29 | return x*rhs.y - y*rhs.x;
30 | }
31 | };
32 |
33 | int main()
34 | {
35 | Point a, b;
36 | Point aa, bb;
37 | }
--------------------------------------------------------------------------------
/geometry/rectangle_union.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | using ll = long long;
6 |
7 | int const maxn = 101010;
8 |
9 | struct Rectangle {
10 | int x1, x2, y1, y2;
11 | };
12 |
13 | enum class Ev {
14 | ini = 1,
15 | fim = -1,
16 | };
17 |
18 | struct Event {
19 | int x;
20 | int y1, y2;
21 | Ev type;
22 |
23 | bool operator<(Event const& rhs) const {
24 | if (x == rhs.x) return type > rhs.type;
25 | return x < rhs.x;
26 | }
27 | };
28 |
29 | struct Seg {
30 | struct Node {
31 | int sum, cnt;
32 | };
33 |
34 | int n;
35 | vector tree;
36 |
37 | void join(int no, int l, int r) {
38 | if (l == r) {
39 | tree[no].sum = (tree[no].cnt >= 1);
40 | }
41 | else if (tree[no].cnt == 0) {
42 | tree[no].sum = tree[no*2+1].sum + tree[no*2+2].sum;
43 | }
44 | else {
45 | tree[no].sum = r-l+1;
46 | }
47 | }
48 |
49 | void upd(int no, int l, int r, int a, int b, Ev add) {
50 | if (a <= l and r <= b) {
51 | tree[no].cnt += static_cast(add);
52 |
53 | join(no, l, r);
54 | }
55 | else {
56 | int m = (l+r)/2;
57 |
58 | if (b <= m) upd(no*2+1, l, m, a, b, add);
59 | else if (a > m) upd(no*2+2, m+1, r, a, b, add);
60 | else {
61 | upd(no*2+1, l, m, a, b, add);
62 | upd(no*2+2, m+1, r, a, b, add);
63 | }
64 |
65 | join(no, l, r);
66 | }
67 | }
68 |
69 | void upd(int a, int b, Ev add) {
70 | upd(0, 0, n, a, b, add);
71 | }
72 |
73 | int get() {
74 | return tree[0].sum;
75 | }
76 |
77 | Seg(int n) : n(n), tree(n*4) {};
78 |
79 | void clear() {
80 | fill(tree.begin(), tree.end(), Node{0, 0});
81 | }
82 | };
83 |
84 |
85 | ll sweep(Seg& seg, vector const& ev) {
86 | ll ans = 0;
87 | seg.clear();
88 |
89 | int last = ev.front().x;
90 |
91 | for (auto&& e : ev) {
92 | ans += ll(e.x - last) * (seg.get());
93 | seg.upd(e.y1, e.y2, e.type);
94 | last = e.x;
95 | }
96 |
97 | return ans;
98 | }
99 |
100 | ll rectangle_union(Seg& seg, vector const& v) {
101 | vector r;
102 |
103 | for (auto&& rect : v) {
104 | r.push_back(Event{rect.x1, rect.y1, rect.y2, Ev::ini});
105 | r.push_back(Event{rect.x2 + 1, rect.y1, rect.y2, Ev::fim});
106 | }
107 |
108 | sort(r.begin(), r.end());
109 |
110 | return sweep(seg, r);
111 | }
112 |
113 |
--------------------------------------------------------------------------------
/graph/bfs.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 101010;
6 |
7 | vector v[maxn];
8 | int vis[maxn];
9 |
10 | void bfs(int x)
11 | {
12 | queue q;
13 | q.push(x);
14 | vis[x] = 1;
15 |
16 | while (!q.empty()) {
17 | int at = q.front();
18 | q.pop();
19 |
20 | // body
21 | for (int u : v[at]) {
22 | if (!vis[u]) {
23 | vis[u] = 1;
24 | q.push(u);
25 | }
26 | }
27 |
28 | // after
29 | }
30 | }
31 |
32 | int main()
33 | {
34 |
35 | }
--------------------------------------------------------------------------------
/graph/biconnected_component.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace std;
3 |
4 | int const maxn = 101010;
5 |
6 | int n;
7 | vector v[maxn];
8 |
9 | struct BiconnectedComponent {
10 | vector low, num, s;
11 | vector> components;
12 | int counter;
13 |
14 | BiconnectedComponent() : num(n, -1), low(n, -1), counter(0) {
15 | for (int i = 0; i < n; i++)
16 | if (num[i] < 0)
17 | dfs(i, 1);
18 | }
19 |
20 | void dfs(int x, int isRoot, int p) {
21 | low[x] = num[x] = ++counter;
22 | if (v[x].empty()) {
23 | components.push_back(vector(1, x));
24 | return;
25 | }
26 | s.push_back(x);
27 |
28 | for (int u : v[x]) {
29 | if (num[u] > -1) low[x] = min(low[x], num[u]);
30 | else {
31 | dfs(u, 0, x);
32 | low[x] = min(low[x], low[u]);
33 |
34 | if (isRoot || low[u] >= num[x]) {
35 | components.push_back(vector(1, x));
36 | while (1) {
37 | int k = s.back();
38 | s.pop_back();
39 | components.back().push_back(k);
40 | if (k == u) break;
41 | }
42 | }
43 | }
44 | }
45 | }
46 | };
47 |
--------------------------------------------------------------------------------
/graph/bridge_articulation.cpp:
--------------------------------------------------------------------------------
1 | struct UndirectedDfs {
2 | vector low, num, parent;
3 | vector articulation;
4 | int counter, root, children;
5 |
6 | vector< pair > bridges;
7 | vector cuts;
8 |
9 | UndirectedDfs() : low(V, 0), num(V, -1), parent(V, 0), articulation(V, false),
10 | counter(0), children(0) {
11 | for(int i = 0; i < V; ++i) if (num[i] == -1) {
12 | root = i; children = 0;
13 | dfs(i);
14 | articulation[root] = (children > 1);
15 | }
16 | for(int i = 0; i < V; ++i)
17 | if (articulation[i]) cuts.push_back(i);
18 | }
19 | private:
20 | void dfs(int u) {
21 | low[u] = num[u] = counter++;
22 | for(int j = 0; j < (int) G[u].size(); ++j) {
23 | int v = G[u][j];
24 | if (num[v] == -1) {
25 | parent[v] = u;
26 | if (u == root) children++;
27 | dfs(v);
28 | if (low[v] >= num[u])
29 | articulation[u] = true;
30 | if (low[v] > num[u]) bridges.push_back(make_pair(u, v));
31 | low[u] = min(low[u], low[v]);
32 | } else if (v != parent[u])
33 | low[u] = min(low[u], num[v]);
34 | }
35 | }
36 | };
--------------------------------------------------------------------------------
/graph/centroid_decomposition.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | using ii = pair;
6 |
7 | const int inf = 0x3f3f3f3f;
8 | const int maxn = 200010;
9 |
10 | int n, k;
11 | vector v[maxn];
12 |
13 | int sz[maxn];
14 | int cvis[maxn];
15 |
16 | int tam(int x, int p)
17 | {
18 | sz[x] = 1;
19 |
20 | for (int u : v[x]) {
21 | if (cvis[u] or u == p) continue;
22 |
23 | sz[x] += tam(u, x);
24 | }
25 |
26 | return sz[x];
27 | }
28 |
29 | int tot;
30 | ii best;
31 |
32 | void split(int x, int p)
33 | {
34 | int heav = tot - sz[x];
35 |
36 | for (int u : v[x]) {
37 | if (cvis[u] or u == p) continue;
38 |
39 | heav = max(heav, sz[u]);
40 | split(u, x);
41 | }
42 |
43 | if (best.second > heav) best = {x, heav};
44 | }
45 |
46 | int centroid(int x)
47 | {
48 | tot = tam(x, x);
49 | best = {0, inf};
50 | split(x, x);
51 | return best.first;
52 | }
53 |
54 | void solve(int x)
55 | {
56 | int cent = centroid(x);
57 | cvis[cent] = 1;
58 |
59 | for (int u : v[cent]) {
60 | if (cvis[u]) continue;
61 | solve(u);
62 | }
63 | }
64 |
65 | int main()
66 | {
67 |
68 | }
--------------------------------------------------------------------------------
/graph/dfs.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 101010;
6 |
7 | vector v[maxn];
8 | int vis[maxn];
9 |
10 | // if general graph
11 | int dfs(int x)
12 | {
13 | vis[x] = 1;
14 | // body
15 | for (int u : v[x])
16 | if (!vis[u]) dfs(u);
17 | // after
18 | }
19 |
20 | // if tree
21 | int dfs(int x, int p)
22 | {
23 | // body
24 | for (int u : v[x]) {
25 | if (u == p) continue;
26 | dfs(u, x);
27 | }
28 | // after
29 | }
--------------------------------------------------------------------------------
/graph/dijkstra.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | typedef pair ii;
6 |
7 | const int maxn = 10101;
8 |
9 | ii v[maxn];
10 | int dist[maxn];
11 |
12 | void sssp(int x)
13 | {
14 | memset(dist, 0x3f, sizeof(dist));
15 | dist[x] = 0;
16 |
17 | priority_queue, greater> pq;
18 | pq.push({0, x});
19 |
20 | while (!pq.empty()) {
21 | int at, w;
22 | tie(w, at) = pq.top();
23 | pq.pop();
24 |
25 | if (w > dist[at]) continue;
26 |
27 | for (ii uu : v[at]) {
28 | int u, ww;
29 | tie(u, ww) = uu;
30 |
31 | if (dist[u] > w+ww) {
32 | dist[u] = w+ww;
33 | pq.push({dist[u], u});
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/graph/dinic.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | using namespace std;
4 |
5 | #define pb push_back
6 | #define eb emplace_back
7 | #define fi first
8 | #define se second
9 | #define mk make_pair
10 |
11 | typedef long long ll;
12 | typedef pair pii;
13 |
14 | const ll INF = 0x3f3f3f3f3f3f3f3f;
15 | const int MAXN = 1e5 + 5;
16 |
17 | template
18 | struct Dinic {
19 | static constexpr T flow_inf = 1e18;
20 |
21 | struct FlowEdge {
22 | int v, u;
23 | T cap, flow = 0;
24 | FlowEdge(int v, int u, T cap) : v(v), u(u), cap(cap) {}
25 | };
26 |
27 | vector edges;
28 | vector> adj;
29 | int n, m = 0;
30 | int s, t;
31 | vector level, ptr;
32 | queue q;
33 |
34 | Dinic(int n, int s, int t) : n(n), s(s), t(t) {
35 | adj.resize(n);
36 | level.resize(n);
37 | ptr.resize(n);
38 | }
39 |
40 | void add_edge(int v, int u, T cap) {
41 | edges.emplace_back(v, u, cap);
42 | edges.emplace_back(u, v, 0);
43 | adj[v].push_back(m);
44 | adj[u].push_back(m + 1);
45 | m += 2;
46 | }
47 |
48 | bool bfs() {
49 | while (!q.empty()) {
50 | int v = q.front();
51 | q.pop();
52 | for (int id : adj[v]) {
53 | if (edges[id].cap - edges[id].flow <= 0)
54 | continue;
55 | if (level[edges[id].u] != -1)
56 | continue;
57 | level[edges[id].u] = level[v] + 1;
58 | q.push(edges[id].u);
59 | }
60 | }
61 | return level[t] != -1;
62 | }
63 |
64 | T dfs(int v, T pushed) {
65 | if (pushed == 0) return 0;
66 |
67 | if (v == t) return pushed;
68 |
69 | for (int& cid = ptr[v]; cid < (int)adj[v].size(); cid++) {
70 | int id = adj[v][cid];
71 | int u = edges[id].u;
72 |
73 | if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow <= 0) continue;
74 |
75 | T tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow));
76 |
77 | if (tr == 0) continue;
78 |
79 | edges[id].flow += tr;
80 | edges[id ^ 1].flow -= tr;
81 |
82 | return tr;
83 | }
84 | return 0;
85 | }
86 |
87 | T flow() {
88 | T f = 0;
89 | while (true) {
90 | fill(level.begin(), level.end(), -1);
91 | level[s] = 0;
92 | q.push(s);
93 | if (!bfs())
94 | break;
95 | fill(ptr.begin(), ptr.end(), 0);
96 | while (T pushed = dfs(s, flow_inf)) {
97 | f += pushed;
98 | }
99 | }
100 | return f;
101 | }
102 | };
103 |
--------------------------------------------------------------------------------
/graph/eulerian_path.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace std;
5 |
6 | int const maxn = 101010;
7 |
8 | vector v[maxn];
9 | int at[maxn];
10 |
11 | void dfs(int x, vector& r) {
12 | while (at[x] < (int)v[x].size()) {
13 | int u = v[x][at[x]];
14 | at[x]++;
15 |
16 | dfs(u, r);
17 | }
18 | r.push_back(x);
19 | }
20 |
21 | int main() {
22 |
23 | }
--------------------------------------------------------------------------------
/graph/hld.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | int const maxn = 101010;
6 |
7 | vector v[maxn];
8 | int val[maxn];
9 |
10 | struct Seg {
11 | Seg(int n) : n(n), tree(n*4) {};
12 |
13 | void upd(int pos, int val) {
14 | upd(1, 0, n-1, pos, val);
15 | }
16 |
17 | int get(int a, int b) {
18 | return get(1, 0, n-1, a, b);
19 | }
20 |
21 | private:
22 | int n;
23 | vector tree;
24 |
25 | void upd(int no, int l, int r, int pos, int val) {
26 | if (l == r) {
27 | tree[no] = val;
28 | return;
29 | }
30 |
31 | int m = (l+r)/2;
32 |
33 | if (pos <= m) upd(no*2, l, m, pos, val);
34 | else upd(no*2+1, m+1, r, pos, val);
35 |
36 | tree[no] = max(tree[no*2], tree[no*2+1]);
37 | }
38 |
39 | int get(int no, int l, int r, int a, int b) {
40 | if (a <= l and r <= b) {
41 | return tree[no];
42 | }
43 | int m = (l+r)/2;
44 |
45 | if (b <= m) return get(no*2, l, m, a, b);
46 | if (a > m) return get(no*2+1, m+1, r, a, b);
47 |
48 | return max(
49 | get(no*2, l, m, a, b),
50 | get(no*2+1, m+1, r, a, b)
51 | );
52 | }
53 | };
54 |
55 | struct HLD {
56 | HLD(int n) : seg(n), par(n), d(n), heav(n, -1), head(n), pos(n), cur_pos(0) {
57 | dfs(0);
58 | decompose(0, 0);
59 | }
60 |
61 | int lca(int a, int b) {
62 | for (; head[a] != head[b]; b = par[head[b]]) {
63 | if (d[head[a]] > d[head[b]]) {
64 | swap(a, b);
65 | }
66 | }
67 | if (d[a] > d[b]) {
68 | return b;
69 | }
70 | else return a;
71 | }
72 |
73 | int max_path(int a, int b) {
74 | int res = 0;
75 | for (; head[a] != head[b]; b = par[head[b]]) {
76 | if (d[head[a]] > d[head[b]]) {
77 | swap(a, b);
78 | }
79 |
80 | res = max(res, seg.get(pos[head[b]], pos[b]));
81 | }
82 | if (d[a] > d[b]) {
83 | swap(a, b);
84 | }
85 | res = max(res, seg.get(pos[a], pos[b]));
86 | return res;
87 | }
88 |
89 | void upd(int x, int val) {
90 | seg.upd(pos[x], val);
91 | }
92 |
93 | private:
94 | Seg seg;
95 | vector par, d, heav, head, pos;
96 | int cur_pos;
97 |
98 | int dfs(int x, int p = -1) {
99 | int sz = 1;
100 | int max_c_size = 0;
101 |
102 | for (int u : v[x]) {
103 | if (u == p) continue;
104 |
105 | par[u] = x;
106 | d[u] = d[x] + 1;
107 |
108 | int c_size = dfs(u, x);
109 | sz += c_size;
110 |
111 | if (c_size > max_c_size) {
112 | max_c_size = c_size;
113 | heav[x] = u;
114 | }
115 | }
116 |
117 | return sz;
118 | }
119 |
120 | void decompose(int x, int h) {
121 | head[x] = h;
122 | pos[x] = cur_pos++;
123 |
124 | seg.upd(pos[x], val[x]);
125 |
126 | if (heav[x] != -1) {
127 | decompose(heav[x], h);
128 | }
129 |
130 | for (int u : v[x]) {
131 | if (u == par[x] or u == heav[x]) continue;
132 | decompose(u, u);
133 | }
134 | }
135 | };
136 |
--------------------------------------------------------------------------------
/graph/hungarian.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | constexpr int inf = numeric_limits::max();
6 |
7 | // finds an answer for the assignment problem using
8 | // the hungarian algorithm in O(n^2*m) [O(n^3)]
9 | // everything is 1 indexed
10 | // ans[0] is the cost of the minimum assignment
11 | struct Hungarian {
12 | Hungarian(vector> const& a) :
13 | n((int)a.size() - 1), m((int)a[0].size() - 1),
14 | u(n+1), v(m+1), p(m+1), way(m+1)
15 | {
16 | for (int i = 1; i <= n; i++) {
17 | p[0] = i;
18 | int j0 = 0;
19 | vector minv (m+1, inf);
20 | vector used (m+1, false);
21 |
22 | do {
23 | used[j0] = true;
24 | int i0 = p[j0], delta = inf, j1;
25 | for (int j = 1; j <= m; j++) {
26 | if (!used[j]) {
27 | int cur = a[i0][j] - u[i0] - v[j];
28 | if (cur < minv[j])
29 | minv[j] = cur, way[j] = j0;
30 | if (minv[j] < delta)
31 | delta = minv[j], j1 = j;
32 | }
33 | }
34 | for (int j = 0; j <= m; j++) {
35 | if (used[j])
36 | u[p[j]] += delta, v[j] -= delta;
37 | else
38 | minv[j] -= delta;
39 | }
40 | j0 = j1;
41 | } while (p[j0] != 0);
42 |
43 | do {
44 | int j1 = way[j0];
45 | p[j0] = p[j1];
46 | j0 = j1;
47 | } while (j0);
48 | }
49 | }
50 |
51 | vector get_ans() {
52 | vector ans (n+1);
53 | for (int j=1; j <= m; j++) {
54 | ans[p[j]] = j;
55 | }
56 | ans[0] = -v[0];
57 | return ans;
58 | }
59 |
60 | private:
61 | int n, m;
62 | vector u, v, p, way;
63 | };
64 |
65 | int main() {
66 | auto print_ans = [] (auto& h) {
67 | auto res = h.get_ans();
68 | for (int i = 1; i < (int)res.size(); i++) {
69 | cout << res[i] << " ";
70 | }
71 | cout << "\n";
72 | };
73 |
74 | Hungarian h(
75 | {{0, 0, 0, 0, 0},
76 | {0, 1, 2, 3, 1},
77 | {0, 1, 2, 3, 1},
78 | {0, 1, 2, 3, 0}}
79 | );
80 |
81 | print_ans(h);
82 | }
--------------------------------------------------------------------------------
/graph/kruskal.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | typedef pair ii;
6 |
7 | const int maxn = 101010;
8 |
9 | template
10 | struct Dsu
11 | {
12 | int pai[size], w[size];
13 |
14 | int find(int x)
15 | {
16 | if (x == pai[x]) return x;
17 | return pai[x] = find(pai[x]);
18 | }
19 |
20 | void join(int x, int y)
21 | {
22 | x = find(x), y = find(y);
23 | if (x == y) return;
24 | if (w[x] < w[y]) swap(x, y);
25 | pai[y] = x;
26 | w[x] += w[y];
27 | }
28 |
29 | void clear()
30 | {
31 | for (int i = 0; i < size; i++)
32 | pai[i] = i, w[i] = 1;
33 | }
34 | };
35 |
36 | struct Edge
37 | {
38 | int a, b, w;
39 |
40 | bool operator<(const Edge& rhs) {
41 | return w < rhs.w;
42 | }
43 | };
44 |
45 | Dsu dsu;
46 |
47 | int kruskal(vector &lista)
48 | {
49 | dsu.clear();
50 | sort(lista.begin(), lista.end());
51 |
52 | int ans = 0;
53 | for (const Edge& ed : lista) {
54 | if (dsu.find(ed.a) == dsu.find(ed.b))
55 | continue;
56 | dsu.join(ed.a, ed.b);
57 | ans += ed.w;
58 | }
59 |
60 | return ans;
61 | }
62 |
63 | int main()
64 | {
65 |
66 | }
--------------------------------------------------------------------------------
/graph/lca_binary_lifting.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 101010;
6 | const int maxlog = 20;
7 |
8 | vector v[maxn];
9 | int dep[maxn];
10 | int anc[maxn][maxlog];
11 |
12 | void dfs(int x, int p)
13 | {
14 | for (int u : v[x]) {
15 | if (u == p) continue;
16 |
17 | anc[u][0] = x;
18 |
19 | for (int i = 1; i < maxlog; i++)
20 | anc[u][i] = anc[anc[u][i-1]][i-1];
21 |
22 | dep[u] = dep[x]+1;
23 | dfs(u, x);
24 | }
25 | }
26 |
27 | int lca(int x, int y)
28 | {
29 | if (x == y) return x;
30 |
31 | if (dep[x] > dep[y]) swap(x, y);
32 |
33 | for (int i = maxlog-1; i >= 0 and dep[x] != dep[y]; i--)
34 | if (dep[y]-(1<= dep[x])
35 | y = anc[y][i];
36 |
37 | if (x == y) return x;
38 | for (int i = maxlog-1; i >= 0; i--)
39 | if (anc[x][i] != anc[y][i] and
40 | anc[x][i] != 0 and anc[y][i] != 0)
41 | x = anc[x][i], y = anc[y][i];
42 |
43 | if (x == y) return x;
44 | return anc[x][0];
45 | }
46 |
47 | int main()
48 | {
49 | int n;
50 | cin >> n;
51 |
52 | for (int i = 0; i < n-1; i++) {
53 | int a, b;
54 | cin >> a >> b;
55 |
56 | v[a].push_back(b);
57 | v[b].push_back(a);
58 | }
59 |
60 | dfs(1, 1);
61 |
62 | while (1) {
63 |
64 | int x, y;
65 | cin >> x >> y;
66 |
67 | if (x == 0) break;
68 |
69 | int ans = lca(x, y);
70 | cout << ans << "\n";
71 | }
72 | }
--------------------------------------------------------------------------------
/graph/maximum_clique.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 20;
6 |
7 | int n, m;
8 | vector v[maxn];
9 |
10 | int solve(int x, int mask, int cnt)
11 | {
12 | if (x == n+1) return cnt;
13 |
14 | int num = 0;
15 | for (int u : v[x]) {
16 | if (mask&(1<> n >> m;
30 |
31 | for (int i = 0; i < m; i++) {
32 | int a, b;
33 | cin >> a >> b;
34 |
35 | v[a].push_back(b);
36 | v[b].push_back(a);
37 | }
38 |
39 | int ans = solve(1, 0, 0);
40 |
41 | cout << ans << "\n";
42 | }
--------------------------------------------------------------------------------
/graph/strongly_connected.cpp:
--------------------------------------------------------------------------------
1 | struct DirectedDfs {
2 | vector num, low, current, S;
3 | int counter;
4 | vector< vector > scc;
5 |
6 | DirectedDfs() : num(V, -1), low(V, 0), current(V, 0), counter(0) {
7 | REP(i,V) if (num[i] == -1) dfs(i);
8 | }
9 |
10 | void dfs(int u) {
11 | low[u] = num[u] = counter++;
12 | S.push_back(u);
13 | current[u] = 1;
14 | for (auto v : G[u]) {
15 | if (num[v] == -1) dfs(v);
16 | if (current[v]) low[u] = min(low[u], low[v]);
17 | }
18 | if (low[u] == num[u]) {
19 | scc.push_back(vector());
20 | while (1) {
21 | int v = S.back(); S.pop_back(); current[v] = 0;
22 | scc.back().push_back(v);
23 | if (u == v) break;
24 | }
25 | }
26 | }
27 | };
--------------------------------------------------------------------------------
/graph/union_find.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace std;
4 |
5 | const int maxn = 101010;
6 |
7 | // Disjoint Set Union / Union-Find
8 | template
9 | struct Dsu
10 | {
11 | // parent and weight of subtree i
12 | int pai[size], w[size];
13 |
14 | // find the superior parent of x
15 | int find(int x)
16 | {
17 | // if x if already the superior parent
18 | if (x == pai[x]) return x;
19 | // compresses the path between x and if superior parent
20 | return pai[x] = find(pai[x]);
21 | }
22 |
23 | // joins the subtree of x and y
24 | void join(int x, int y)
25 | {
26 | // finds the subtree each x and y are part of
27 | x = find(x), y = find(y);
28 |
29 | // if already joined : nothing to do
30 | if (x == y) return;
31 |
32 | // x must have more elements than y in order
33 | // to have the small-to-large preperty
34 | if (w[x] < w[y]) swap(x, y);
35 |
36 | // x becomes the superior parent of y
37 | pai[y] = x;
38 |
39 | // fix weights
40 | w[x] += w[y];
41 | }
42 |
43 | void clear()
44 | {
45 | // initialize every set x to contain only x
46 | // (empty sets)
47 | for (int i = 0; i < size; i++)
48 | pai[i] = i, w[i] = 1;
49 | }
50 | };
51 |
52 | Dsu dsu;
53 |
54 | int main()
55 | {
56 |
57 | }
--------------------------------------------------------------------------------
/math/bigint.cpp:
--------------------------------------------------------------------------------
1 | // NOTE:
2 | // This code contains various bug fixes compared to the original version from
3 | // indy256 (github.com/indy256/codelibrary/blob/master/cpp/numbertheory/bigint-full.cpp),
4 | // including:
5 | // - Fix overflow bug in mul_karatsuba.
6 | // - Fix overflow bug in fft.
7 | // - Fix bug in initialization from long long.
8 | // - Optimized operators + - *.
9 | //
10 | // Tested:
11 | // - https://www.e-olymp.com/en/problems/266: Comparison
12 | // - https://www.e-olymp.com/en/problems/267: Subtraction
13 | // - https://www.e-olymp.com/en/problems/271: Multiplication
14 | // - https://www.e-olymp.com/en/problems/272: Multiplication
15 | // - https://www.e-olymp.com/en/problems/313: Addition
16 | // - https://www.e-olymp.com/en/problems/314: Addition/Subtraction
17 | // - https://www.e-olymp.com/en/problems/317: Multiplication (simple / karatsuba / fft)
18 | // - https://www.e-olymp.com/en/problems/1327: Multiplication
19 | // - https://www.e-olymp.com/en/problems/1328
20 | // - VOJ BIGNUM: Addition, Subtraction, Multiplication.
21 | // - SGU 111: sqrt
22 | // - SGU 193
23 | // - SPOJ MUL, VFMUL: Multiplication.
24 | // - SPOJ FDIV, VFDIV: Division.
25 |
26 | #include
27 |
28 | using namespace std;
29 |
30 | using ll = long long;
31 |
32 | const int BASE_DIGITS = 9;
33 | const int BASE = 1000000000;
34 |
35 | struct BigInt {
36 | int sign;
37 | vector a;
38 |
39 | // -------------------- Constructors --------------------
40 | // Default constructor.
41 | BigInt() : sign(1) {}
42 |
43 | // Constructor from long long.
44 | BigInt(long long v) {
45 | *this = v;
46 | }
47 | BigInt& operator = (long long v) {
48 | sign = 1;
49 | if (v < 0) {
50 | sign = -1;
51 | v = -v;
52 | }
53 | a.clear();
54 | for (; v > 0; v = v / BASE)
55 | a.push_back(v % BASE);
56 | return *this;
57 | }
58 |
59 | // Initialize from string.
60 | BigInt(const string& s) {
61 | read(s);
62 | }
63 |
64 | // -------------------- Input / Output --------------------
65 | void read(const string& s) {
66 | sign = 1;
67 | a.clear();
68 | int pos = 0;
69 | while (pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) {
70 | if (s[pos] == '-')
71 | sign = -sign;
72 | ++pos;
73 | }
74 | for (int i = s.size() - 1; i >= pos; i -= BASE_DIGITS) {
75 | int x = 0;
76 | for (int j = max(pos, i - BASE_DIGITS + 1); j <= i; j++)
77 | x = x * 10 + s[j] - '0';
78 | a.push_back(x);
79 | }
80 | trim();
81 | }
82 | friend istream& operator>>(istream &stream, BigInt &v) {
83 | string s;
84 | stream >> s;
85 | v.read(s);
86 | return stream;
87 | }
88 |
89 | friend ostream& operator<<(ostream &stream, const BigInt &v) {
90 | if (v.sign == -1 && !v.isZero())
91 | stream << '-';
92 | stream << (v.a.empty() ? 0 : v.a.back());
93 | for (int i = (int) v.a.size() - 2; i >= 0; --i)
94 | stream << setw(BASE_DIGITS) << setfill('0') << v.a[i];
95 | return stream;
96 | }
97 |
98 | // -------------------- Comparison --------------------
99 | bool operator<(const BigInt &v) const {
100 | if (sign != v.sign)
101 | return sign < v.sign;
102 | if (a.size() != v.a.size())
103 | return a.size() * sign < v.a.size() * v.sign;
104 | for (int i = ((int) a.size()) - 1; i >= 0; i--)
105 | if (a[i] != v.a[i])
106 | return a[i] * sign < v.a[i] * sign;
107 | return false;
108 | }
109 |
110 | bool operator>(const BigInt &v) const {
111 | return v < *this;
112 | }
113 | bool operator<=(const BigInt &v) const {
114 | return !(v < *this);
115 | }
116 | bool operator>=(const BigInt &v) const {
117 | return !(*this < v);
118 | }
119 | bool operator==(const BigInt &v) const {
120 | return !(*this < v) && !(v < *this);
121 | }
122 | bool operator!=(const BigInt &v) const {
123 | return *this < v || v < *this;
124 | }
125 |
126 | // Returns:
127 | // 0 if |x| == |y|
128 | // -1 if |x| < |y|
129 | // 1 if |x| > |y|
130 | friend int __compare_abs(const BigInt& x, const BigInt& y) {
131 | if (x.a.size() != y.a.size()) {
132 | return x.a.size() < y.a.size() ? -1 : 1;
133 | }
134 |
135 | for (int i = ((int) x.a.size()) - 1; i >= 0; --i) {
136 | if (x.a[i] != y.a[i]) {
137 | return x.a[i] < y.a[i] ? -1 : 1;
138 | }
139 | }
140 | return 0;
141 | }
142 |
143 | // -------------------- Unary operator - and operators +- --------------------
144 | BigInt operator-() const {
145 | BigInt res = *this;
146 | if (isZero()) return res;
147 |
148 | res.sign = -sign;
149 | return res;
150 | }
151 |
152 | // Note: sign ignored.
153 | void __internal_add(const BigInt& v) {
154 | if (a.size() < v.a.size()) {
155 | a.resize(v.a.size(), 0);
156 | }
157 | for (int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) {
158 | if (i == (int) a.size()) a.push_back(0);
159 |
160 | a[i] += carry + (i < (int) v.a.size() ? v.a[i] : 0);
161 | carry = a[i] >= BASE;
162 | if (carry) a[i] -= BASE;
163 | }
164 | }
165 |
166 | // Note: sign ignored.
167 | void __internal_sub(const BigInt& v) {
168 | for (int i = 0, carry = 0; i < (int) v.a.size() || carry; ++i) {
169 | a[i] -= carry + (i < (int) v.a.size() ? v.a[i] : 0);
170 | carry = a[i] < 0;
171 | if (carry) a[i] += BASE;
172 | }
173 | this->trim();
174 | }
175 |
176 | BigInt operator += (const BigInt& v) {
177 | if (sign == v.sign) {
178 | __internal_add(v);
179 | } else {
180 | if (__compare_abs(*this, v) >= 0) {
181 | __internal_sub(v);
182 | } else {
183 | BigInt vv = v;
184 | swap(*this, vv);
185 | __internal_sub(vv);
186 | }
187 | }
188 | return *this;
189 | }
190 |
191 | BigInt operator -= (const BigInt& v) {
192 | if (sign == v.sign) {
193 | if (__compare_abs(*this, v) >= 0) {
194 | __internal_sub(v);
195 | } else {
196 | BigInt vv = v;
197 | swap(*this, vv);
198 | __internal_sub(vv);
199 | this->sign = -this->sign;
200 | }
201 | } else {
202 | __internal_add(v);
203 | }
204 | return *this;
205 | }
206 |
207 | // Optimize operators + and - according to
208 | // https://stackoverflow.com/questions/13166079/move-semantics-and-pass-by-rvalue-reference-in-overloaded-arithmetic
209 | template< typename L, typename R >
210 | typename std::enable_if<
211 | std::is_convertible