diff --git a/caderno.pdf b/caderno.pdf index 4b60aff95fa63be0f9c9d35e203505322483f7a7..c9fc0a587da84d4d9a66a59ac7c5ddaf87fdd58c 100644 Binary files a/caderno.pdf and b/caderno.pdf differ diff --git a/caderno/caderno.tex b/caderno/caderno.tex index 1444998d3504c3d90635f11e8c6c9f4148ab0aca..114f2b982a09bfab2da6b8b30ad7819fe0a46a1e 100644 --- a/caderno/caderno.tex +++ b/caderno/caderno.tex @@ -208,6 +208,9 @@ para $a$ e $m$ coprimos. \importsource{fenwick-range-tree.h} +\subsection{Tabela esparsa} +\importsource{sparse-table.h} + \subsection{União-busca} \importsource{disjoint.h} @@ -235,15 +238,15 @@ para $a$ e $m$ coprimos. \subsection{Próximo menor elemento} \importsource{nle.h} +\subsection{Conjunto de intervalos coloridos} +\importsource{interval-set.h} + \subsection{Hash map simples} \importsource{simple-hash.h} \subsection{Hash customizado} \importsource{custom-hash.h} -\subsection{Conjunto de intervalos coloridos} -\importsource{interval-set.h} - \subsection{Árvore de segmentos recursiva} \begin{tabular}{l|l|l} \hline @@ -273,12 +276,13 @@ para $a$ e $m$ coprimos. \subsection{Árvore de segmentos preguiçosa rec.} \importsource{lstrec.h} -\subsection{Árvore de segmentos preguiçosa iter.} -\importsource{lstit.h} - \subsection{Nó de árvore de segmentos} \importsource{node.h} +\clearpage +\subsection{Árvore de segmentos preguiçosa iter.} +\importsource{lstit.h} + \section{Grafos} \subsection{Articulações e Pontes} @@ -287,6 +291,7 @@ para $a$ e $m$ coprimos. \subsection{Stoer-Wagner} \importsource{stoer-wagner.h} +\clearpage \subsection{Emparelhamento estável} \begin{tabular}{l} \hline @@ -331,7 +336,7 @@ para $a$ e $m$ coprimos. \subsection{Caminhos mínimos -- Floyd-Warshall} \importsource{floyd-warshall.h} -\subsection{Ordenação Topológica} +\subsection{Ordenação topológica} \importsource{topo.h} \subsection{Árvore geradora mínima -- Prim} @@ -343,6 +348,10 @@ para $a$ e $m$ coprimos. \subsection{Ascensão binária} \importsource{bl.h} +\subsection{Menor anc. comum -- Offline} +\importsource{lca-offline.h} + +\clearpage \subsection{Menor anc. comum -- Ancensão binária} \importsource{bllca.h} @@ -361,12 +370,6 @@ para $a$ e $m$ coprimos. \end{tabular} \importsource{hld.h} -\subsection{Decomposição raiz quadrada de árvore} -\importsource{stdt.h} - -\subsection{Menor anc. comum -- Dec. raiz quad.} -\importsource{stdtlca.h} - \subsection{Empar. máximo bipartido -- Kuhn} \begin{tabular}{l} \hline @@ -378,13 +381,30 @@ para $a$ e $m$ coprimos. \subsection{Empar. máximo bipartido -- Hopcroft} \importsource{hopcroft.h} -\section{Matemática} +\subsection{Decomposição raiz quadrada de árvore} +\importsource{stdt.h} -\subsection{Problema de Josephus} +\subsection{Menor anc. comum -- Dec. raiz quad.} +\importsource{stdtlca.h} + +\section{Matemática} \subsection{Operações comuns} \importsource{numbers.h} +\subsection{Compressão de coordenadas} +\importsource{coordmap.h} + +\subsection{Sequência de Bruijn} +Número de sequências distintas: +\begin{align*} + \frac{(k!)^{k^{n-1}}}{k^n} +\end{align*} +\importsource{bruijn.h} + +\subsection{Problema de Josephus} +\importsource{josephus.h} + \subsection{Primeiros e últimos digitos de $n^k$} \importsource{nk-first-last-digits.h} @@ -512,6 +532,7 @@ ax + by = c \subsection{Miller-Rabin} \importsource{miller-rabin.h} +\clearpage \subsection{Pollard Rho} \begin{tabular}{l} \hline @@ -556,6 +577,7 @@ $z[i]$ é o tamanho da maior string que é ao mesmo tempo, um prefixo de $s$ e u \importsource{z.h} +\clearpage \subsection{KMP} \begin{tabular}{l|l} \hline @@ -601,9 +623,6 @@ $z[i]$ é o tamanho da maior string que é ao mesmo tempo, um prefixo de $s$ e u \end{tabular} \importsource{graham.h} -\subsection{Interseção de retângulos} -\importsource{rectangle-intersection.h} - \subsection{Ponto dentro do polígono?} \importsource{isinsidepoly.h} @@ -625,54 +644,76 @@ A = i + b/2 - 1 \subsection{Ponto e segmento} \importsource{pointseg.h} +\subsection{Interseção de retângulos} +\importsource{rectangle-intersection.h} + \subsection{Segmento e segmento} \importsource{segseg.h} \subsection{Árvore KD} \importsource{kd-tree.h} -\subsection{Varredura linear*} - \subsection{Varredura angular} \importsource{angular-sweep.h} -\section{Problemas} -\subsection{Rainhas no tabuleiro*} +\section{Algoritmos} -\subsection{Soma em subvetor*} +\subsection{Agendamento ótimo de tarefas} +\importsource{jobs.h} -\subsection{Remoção de valores com deque*} +\subsection{Ordenação por fusão} +\importsource{mergesort.h} -\subsection{Remoção de valores com lista*} +\subsection{Subconjuntos de tamanho $K$} +\importsource{combination.h} -\subsection{Embarcadouro*} +\subsection{Algoritmo de Mo} +\importsource{mo.h} -\section{Algoritmos} -\subsection{Ordenação por fusão*} -\importsource{merge-sort.h} +\subsection{Meet in the middle} +\importsource{meet.h} -\subsection{Mochila com recuperação*} +\subsection{Maior subvetor com soma $s$} +\importsource{subsum.h} -\subsection{Permutações*} +\subsection{Maior subsequência crescente} +\importsource{lis.h} -\subsection{Algoritmo de Mo*} +\subsection{Maior subsequência crescente rápido} +\importsource{lisnlgn.h} -\subsection{Meet in the middle*} +\subsection{PD de perfil quebrado} +\importsource{parquet.h} -\subsection{Maior subsequência crescente*} -\importsource{lis.cpp} +\subsection{Busca binária} +\importsource{bs.h} -\subsection{Maior subsequência crescente mais rápido*} -\importsource{lisnlgn.cpp} +\subsection{Máscaras de bit e operações em bit} +\importsource{bitmask.h} -\subsection{PD de perfil quebrado*} +\subsection{Busca binária diferentona} +\importsource{binarystep.h} -\subsection{Busca binária} -\importsource{bs.h} +\section{Problemas} +\subsection{Rainhas no tabuleiro} +\importsource{queens.h} + +\subsection{Moda usando algoritmo de Mo} +\importsource{mode.h} + +\subsection{Inversões usando algoritmo de Mo} +\importsource{inversionmo.h} + +\subsection{Remoção de valores com lista} +\importsource{remove.h} + +\subsection{Remoção de valores com deque} +\importsource{removedeque.h} -\subsection{Busca binária diferentona*} +\subsection{Desembarcadouro} +\importsource{desembarcadouro.h} -\subsection{Máscaras de bit e operações em bit*} -\importsource{bit-ops.cpp} +\subsection{Distância de Edição} +\importsource{edit-distance.h} \end{document} diff --git a/fontes/binarystep.h b/fontes/binarystep.h new file mode 100644 index 0000000000000000000000000000000000000000..0aa69e916baba9e58683c125e70d2824d9b9001a --- /dev/null +++ b/fontes/binarystep.h @@ -0,0 +1,9 @@ +int count(vector<int>& v, int x) { + int n = v.size(); + int l = n, r = n; + for (int p = n; p >= 1; p /= 2) { + while (l-p >= 0 && !(v[l-p] < 2)) { l -= p; } + while (r-p >= 0 && !(v[r-p] <= 2)) { r -= p; } + } + return r - l; +} diff --git a/fontes/bit-ops.cpp b/fontes/bitmask.h similarity index 50% rename from fontes/bit-ops.cpp rename to fontes/bitmask.h index 6b589436052964decf4cd273693b0dda7202dbc0..fc49afd8c0db70f9119f0927df94f36b4d6b9f42 100644 --- a/fontes/bit-ops.cpp +++ b/fontes/bitmask.h @@ -1,3 +1,3 @@ for (int s = 0; s < (1LL<<n); s++) for (int ss = s; ss > 0; ss = (ss-1)&s) - minCost[i][s] = min(minCost[i][s], minCost[i][ss] + minCost[i][s-ss]); + c[i][s] = min(c[i][s], c[i][ss] + c[i][s-ss]); diff --git a/fontes/bruijn.h b/fontes/bruijn.h new file mode 100644 index 0000000000000000000000000000000000000000..5d09f534bfe9ac43c1f5c07080d412cbaeaae938 --- /dev/null +++ b/fontes/bruijn.h @@ -0,0 +1,14 @@ +vector<int> a (K*N, 0); +vector<int> seq; + +void de_bruijn(int k, int n, int t=1, int p=1) { + if (t > n && n % p == 0) + seq.insert(end(seq), begin(a)+1, begin(a)+p+1); + if (t > n) { return; } + a[t] = a[t - p]; + de_bruijn(k, n, t+1, p); + for (int j = a[t-p]+1; j < k; j++) { + a[t] = j; + de_bruijn(k, n, t+1, t); + } +} diff --git a/fontes/bs.h b/fontes/bs.h index d761a7d724b9b576a769ef5208cca47b096707cd..46ebc2907e44286c2415e70761870dfac2165803 100644 --- a/fontes/bs.h +++ b/fontes/bs.h @@ -1,16 +1,9 @@ ll binary_search(ll lo, ll hi) { while (lo < hi) { ll mid = lo + (hi-lo) / 2; - if (P(mid)) { - hi = mid; - } else { - lo = mid + 1; - } + if (P(mid)) { hi = mid; } + else { lo = mid + 1; } } - - if (!P(lo)) { - // P(x) is false for all x in S - } - + if (!P(lo)) { /* P(x) is false for all x in S */ } return lo; } diff --git a/fontes/combination.h b/fontes/combination.h new file mode 100644 index 0000000000000000000000000000000000000000..ef6b7cae1a4f7fa87fafc1171095ef5bd41c269f --- /dev/null +++ b/fontes/combination.h @@ -0,0 +1,12 @@ +bool next_combination(vector<int>& a, int n) { + int k = a.size(); + for (int i = k - 1; i >= 0; i--) { + if (a[i] < n - k + i + 1) { + a[i]++; + for (int j = i + 1; j < k; j++) + a[j] = a[j - 1] + 1; + return true; + } + } + return false; +} diff --git a/fontes/coordmap.h b/fontes/coordmap.h new file mode 100644 index 0000000000000000000000000000000000000000..26299316f82b591e87c91d11dc5022b6ccf90c29 --- /dev/null +++ b/fontes/coordmap.h @@ -0,0 +1,8 @@ +void compress(vector<int>& v, vector<int>& cv) { + set<int> vs (v.begin(), v.end()); + map<int, int> to, fm; + int ix = 0; + for (int i : vs) { to[i] = ix; fm[ix] = i; ix++; } + for (int i = 0; i < v.size(); i++) + cv[i] = to[v[i]]; +} diff --git a/fontes/desembarcadouro.h b/fontes/desembarcadouro.h new file mode 100644 index 0000000000000000000000000000000000000000..09e73c6932d50ebf9cbf45d21c758616007fa5f4 --- /dev/null +++ b/fontes/desembarcadouro.h @@ -0,0 +1,20 @@ +const int K = 300; +vector<int> containers (100001); +vector<vector<int>> dp (100001 + K, vector<int>(K)); +int main() { + int n, q; cin >> n >> q; + while (q--) { + int a, l, d; cin >> a >> l >> d; + if (d >= K) + for (int i = 0; i < l; i++) { containers[a + i * d]++; } + else { dp[a][d]++; dp[a + (l * d)][d]--; } + } + for (int j = 1; j < K; j++) + for (int i = j; i < n + 1; i++) + dp[i][j] += dp[i - j][j]; + for (int i = 1; i <= n; i++) { + for (int j = 1; j < K; j++) + containers[i] += dp[i][j]; + cout << containers[i] << ' '; + } +} diff --git a/fontes/edit-distance.h b/fontes/edit-distance.h new file mode 100644 index 0000000000000000000000000000000000000000..7fb89626e78310f26dec2b52d2370f79078aac3c --- /dev/null +++ b/fontes/edit-distance.h @@ -0,0 +1,29 @@ +void edit_distance(string s1, s2) { + int n1 = s1.size(), n2 = s2.size(); + vector<vector<int>> dist (n1+1, vector<int>(n2+1)); + vector<vector<int>> op (n1+1, vector<int>(n2+1)); + for (int i = 1; i <= n1; i++) { + dist[i][0] = i; op[i][0] = 3; + } + for (int j = 1; j <= n2; j++) { + dist[0][j] = j; op[0][j] = 2; + } + for (int i = 1; i <= n1; i++) + for (int j = 1; j <= n2; j++) { + int bdist, bop; + if (s1[i-1] == s2[j-1]) { + // Skip + bdist = dist[i-1][j-1]; bop = 0; + } else { + int repl = dist[i-1][j-1] + 1; + bdist = repl; bop = 1; + int ins = dist[i][j-1] + 1; + if (ins < bdist) { bdist = ins; bop = 2; } + int del = dist[i-1][j] + 1; + if (del < bdist) { bdist = del; bop = 3; } + } + dist[i][j] = bdist; + op[i][j] = bop; + } + return dist[n1][n2]; +} diff --git a/fontes/floyd-warshall.h b/fontes/floyd-warshall.h index 510f550260ebf915fc71051dd5fb0b8905f104dc..df7d13beb6196e1fae48f43135d3528c61d67213 100644 --- a/fontes/floyd-warshall.h +++ b/fontes/floyd-warshall.h @@ -1,6 +1,6 @@ vector<vector<ll>> d (N, vector<ll>(N, oo)); -int floydwarshall(int n) { +void floydwarshall(int n) { for (int u = 0; u < n; u++) d[u][u] = 0; for (int m = 0; m < n; m++) diff --git a/fontes/floyd.h b/fontes/floyd.h index 586099bfc2e6275a05da81ebd06af14ab2abeff8..06eabe47309148af0fc57e1346589c73529a759e 100644 --- a/fontes/floyd.h +++ b/fontes/floyd.h @@ -1,14 +1,11 @@ struct cyc { ll prev, first, len; }; cyc find_cycle(ll start) { - ll a = start, b = start; - do { - a = succ(a); - b = succ(succ(b)); - } while (a != b); - a = start; - ll prev = -1; - while (a != b) { prev = a; a = succ(a); b = succ(b); } - ll len = 0; - do { b = succ(b); len++; } while (a != b); - return { .prev = prev, .first = a, .len = len }; + ll a = start, b = start; + do { a = succ(a); b = succ(succ(b)); } while (a != b); + a = start; + ll prev = -1; + while (a != b) { prev = a; a = succ(a); b = succ(b); } + ll len = 0; + do { b = succ(b); len++; } while (a != b); + return { .prev = prev, .first = a, .len = len }; } diff --git a/fontes/floydhash.h b/fontes/floydhash.h deleted file mode 100644 index b0a3fade7b4eaf7ba16007efaddfa826dc0cc988..0000000000000000000000000000000000000000 --- a/fontes/floydhash.h +++ /dev/null @@ -1,16 +0,0 @@ -ll polyhash(string const& s) { - ll h = 0, p = 1; - for (char c : s) { - h += (c-'a'+1) * p; h %= M; - p *= P; p %= M; } - return h; -} -string gen(ll u) { - mt19937_64 rnd (u); u = rnd(); - string s; - while (u) { s += ('a'+(u%26)); u /= 26; } - return s; -} -ll succ(ll u) { - return polyhash(gen(u)); -} diff --git a/fontes/gen.cpp b/fontes/gen.cpp index 9d9c432246b52a77f1630b1c1a079479f3c27a3a..f23704652c06671e7d25539b2a3dfeeee2f147e7 100644 --- a/fontes/gen.cpp +++ b/fontes/gen.cpp @@ -1,19 +1,11 @@ -#include <bits/stdc++.h> -using namespace std; using ll = long long; - mt19937 rnd; - ll gen(ll a, ll b) { uniform_int_distribution<ll> dist (a, b); return dist(rnd); } - int main(int argc, char* argv[]) { - cin.tie(0); ios_base::sync_with_stdio(0); if (argc < 2) { - cerr << "usage: " << argv[0] << " <seed>\n"; - return 1; + cerr << "usage: " << argv[0] << " <seed>\n"; return 1; } rnd = mt19937(atoi(argv[1])); - cout << gen(1, 10) << "\n"; } diff --git a/fontes/interval-set.h b/fontes/interval-set.h index 6368c3aac30bff72acd07da01a1a50b0988c2708..5946f8642497ce888505ab7255600ad6179fc1ea 100644 --- a/fontes/interval-set.h +++ b/fontes/interval-set.h @@ -3,11 +3,8 @@ struct itvl { itvl(int _a, int _b, int _c) : a(_a), b(_b), c(_c) {} bool operator<(const itvl& o) const { - return ii(b, a) < ii(o.b, o.a); - } - bool operator<(const int& o) const { - return b < o; - } + return ii(b, a) < ii(o.b, o.a); } + bool operator<(const int& o) const { return b < o; } }; set<itvl, less<>>& si; @@ -29,8 +26,7 @@ void ins_in(itvl in) { void upd_color(int a, int b, int c) { auto it = si.lower_bound(b); if (it != si.end()) { - itvl ori = *it; - si.erase(it); + itvl ori = *it; si.erase(it); if (ori.a < a) { ins_in(itvl(ori.a, a-1, v)); } if (ori.b > b) { ins_in(itvl(b+1, ori.b, v)); } } diff --git a/fontes/inversionmo.h b/fontes/inversionmo.h new file mode 100644 index 0000000000000000000000000000000000000000..e69a729de8fd28db83ff8c4d8708c65f4b408965 --- /dev/null +++ b/fontes/inversionmo.h @@ -0,0 +1,12 @@ +ll ans = 0; +void ins(int i, char dir) { + if (dir == 'l') { ans += query(v[i]-1); } + else { ans += query(N) - query(v[i]); } + add(v[i], +1); +} +void rem(int i, char dir) { + if (dir == 'l') { ans -= query(v[i]-1); } + else { ans -= query(N) - query(v[i]); } + add(v[i], -1); +} +ll get_ans() { return ans; } diff --git a/fontes/jobs.h b/fontes/jobs.h new file mode 100644 index 0000000000000000000000000000000000000000..140d965d32d7de4f93e6d2cc7d8ae9c894624736 --- /dev/null +++ b/fontes/jobs.h @@ -0,0 +1,25 @@ +struct job { + int deadline, duration, idx; + bool operator<(job o) const { return deadline < o.deadline; } +}; + +vector<int> compute_schedule(vector<job> jobs) { + sort(jobs.begin(), jobs.end()); + set<pair<int,int>> s; vector<int> schedule; + for (int i = jobs.size()-1; i >= 0; i--) { + int t = jobs[i].deadline - (i ? jobs[i-1].deadline : 0); + s.insert(make_pair(jobs[i].duration, jobs[i].idx)); + while (t && !s.empty()) { + auto it = s.begin(); + if (it->first <= t) { + t -= it->first; + schedule.push_back(it->second); + } else { + s.insert(make_pair(it->first - t, it->second)); + t = 0; + } + s.erase(it); + } + } + return schedule; +} diff --git a/fontes/josephus.h b/fontes/josephus.h new file mode 100644 index 0000000000000000000000000000000000000000..c9ea0cf86735420d80e9d90815c5abef225980c1 --- /dev/null +++ b/fontes/josephus.h @@ -0,0 +1,15 @@ +int rec(int n, int k) { + return (rec(n-1, k) + k) % n; +} + +int klogn(int n, int k) { + if (n == 1) { return 0; } + if (k == 1) { return n-1; } + if (k > n) { return (klogn(n-1, k) + k) % n; } + int cnt = n / k; + int res = klogn(n - cnt, k); + res -= n % k; + if (res < 0) { res += n; } + else { res += res / (k - 1); } + return res; +} diff --git a/fontes/karatsuba.h b/fontes/karatsuba.h index d3ca7812bf8ed49036f288b68073c93891158a43..cb0e33b64b9f8cc326782d34e9514e7b57eec2f7 100644 --- a/fontes/karatsuba.h +++ b/fontes/karatsuba.h @@ -2,41 +2,26 @@ vector<ll> karatsuba(const vector<ll> &a, const vector<ll> &b) { int n = a.size(); vector<ll> res(n + n); - if (n <= 32) { for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) res[i + j] += a[i] * b[j]; - return res; } - int k = n >> 1; vector<ll> a1(a.begin(), a.begin() + k); vector<ll> a2(a.begin() + k, a.end()); vector<ll> b1(b.begin(), b.begin() + k); vector<ll> b2(b.begin() + k, b.end()); - vector<ll> a1b1 = karatsuba(a1, b1); vector<ll> a2b2 = karatsuba(a2, b2); - - for (int i = 0; i < k; i++) - a2[i] += a1[i]; - for (int i = 0; i < k; i++) - b2[i] += b1[i]; - + for (int i = 0; i < k; i++) a2[i] += a1[i]; + for (int i = 0; i < k; i++) b2[i] += b1[i]; vector<ll> r = karatsuba(a2, b2); - for (int i = 0; i < a1b1.size(); i++) - r[i] -= a1b1[i]; - for (int i = 0; i < a2b2.size(); i++) - r[i] -= a2b2[i]; - - for (int i = 0; i < r.size(); i++) - res[i + k] += r[i]; - for (int i = 0; i < a1b1.size(); i++) - res[i] += a1b1[i]; - for (int i = 0; i < a2b2.size(); i++) - res[i + n] += a2b2[i]; - + for (int i = 0; i < a1b1.size(); i++) r[i] -= a1b1[i]; + for (int i = 0; i < a2b2.size(); i++) r[i] -= a2b2[i]; + for (int i = 0; i < r.size(); i++) res[i+k] += r[i]; + for (int i = 0; i < a1b1.size(); i++) res[i] += a1b1[i]; + for (int i = 0; i < a2b2.size(); i++) res[i+n] += a2b2[i]; return res; } diff --git a/fontes/kd-tree.h b/fontes/kd-tree.h index 2e62a459117c5e9b1c17f063bdeccb106d8dd7cf..60cea2552a7322393bc0b8a818823d743d3200da 100644 --- a/fontes/kd-tree.h +++ b/fontes/kd-tree.h @@ -1,6 +1,6 @@ int get_ii(pt pair, int ix) { - if (ix == 0) { return pair.px; } - else { return pair.py; } + if (ix == 0) { return pair.px; } + else { return pair.py; } } class kdtree { diff --git a/fontes/kuhn.h b/fontes/kuhn.h index 07e43a93cf9c28694d10adef89d4a2ba43b2423e..f5fee6fb6d8355659b9401ef0192e9e95011aaab 100644 --- a/fontes/kuhn.h +++ b/fontes/kuhn.h @@ -1,4 +1,3 @@ -// u e v são enumerações distintas (podem repetir) vector<vector<int>> g (L); vector<int> matchr (R, -1); diff --git a/fontes/latticepoints.h b/fontes/latticepoints.h index 07fcbf13d44a91555c65776390dcc5309971f058..14bc9a0b057f58b1fc44aa8f672558db7f2fddf1 100644 --- a/fontes/latticepoints.h +++ b/fontes/latticepoints.h @@ -2,14 +2,12 @@ ll lattice_points(vector<pt>& ps) { ll b = 0; for (int i = 0; i < n; i++) { pt v = vec(ps[i], ps[(i+1)%n]); - if (v.py == 0) { + if (v.py == 0) b += abs(v.px); - } else if (v.px == 0) { + else if (v.px == 0) b += abs(v.py); - } else { + else b += gcd(abs(v.px), abs(v.py)); - } } - return poly_area(ps) - b/2 + 1; } diff --git a/fontes/lca-offline.h b/fontes/lca-offline.h new file mode 100644 index 0000000000000000000000000000000000000000..ee011d3dbe0dd2c6858b776e4c1a7d67bbbffede --- /dev/null +++ b/fontes/lca-offline.h @@ -0,0 +1,14 @@ +vector<vector<int>> queries (N); +vector<int> anc (N); vector<bool> vis (N); + +void dfs(int u) { + vis[u] = true; + anc[u] = u; + for (int v : adj[u]) if (!vis[v]) { + dfs(v); + ds_unite(u, v); + anc[ds_find(u)] = u; + } + for (int v : queries[u]) if (vis[v]) + lca[u][v] = anc[ds_find(v)]; +} diff --git a/fontes/lcm.cpp b/fontes/lcm.cpp deleted file mode 100644 index ddbbb5dcf97926ce626995ea1cb981cbfe7c02e2..0000000000000000000000000000000000000000 --- a/fontes/lcm.cpp +++ /dev/null @@ -1,3 +0,0 @@ -int lcm(int a, int b) { - return a*b / __gcd(a, b); -} diff --git a/fontes/lis.cpp b/fontes/lis.cpp deleted file mode 100644 index fe37a36e47e287f5a28c17d64104eadb142f12b4..0000000000000000000000000000000000000000 --- a/fontes/lis.cpp +++ /dev/null @@ -1,9 +0,0 @@ -int n; while (cin >> n) { - fill(dp.begin(), dp.end(), 1); // base - for (int i = 0; i < n; i++) { - cin >> v[i]; - for (int j = 0; j < i; j++) if (v[j] < v[i]) - dp[i] = max(dp[i], 1 + dp[j]); - } - cout << *max_element(dp.begin(), dp.end()) << "\n"; -} diff --git a/fontes/lis.h b/fontes/lis.h new file mode 100644 index 0000000000000000000000000000000000000000..105686802da562f27bc1ed769b63aeb41e79a26f --- /dev/null +++ b/fontes/lis.h @@ -0,0 +1,8 @@ +vector<int> dp (N, 1); + +int lis(vector<int>& v) { + for (int i = 0; i < v.size(); i++) + for (int j = 0; j < i; j++) if (v[j] < v[i]) + dp[i] = max(dp[i], 1 + dp[j]); + return *max_element(dp.begin(), dp.end()); +} diff --git a/fontes/lisnlgn.cpp b/fontes/lisnlgn.h similarity index 61% rename from fontes/lisnlgn.cpp rename to fontes/lisnlgn.h index f3dda8b052f697802c123260ef6b16757d7d60d1..8c4f4d684b10f79021f0d63f9690563da96b3391 100644 --- a/fontes/lisnlgn.cpp +++ b/fontes/lisnlgn.h @@ -1,8 +1,9 @@ -int n; while (cin >> n) { - fill(dp.begin(), dp.begin()+n+1, oo); +vector<int> dp (N, oo); + +int lis(vector<int>& v) { + int n = v.size(); dp[0] = -oo; for (int i = 0; i < n; i++) { - cin >> v[i]; int j = upper_bound(dp.begin(), dp.begin()+n+1, v[i]) - dp.begin(); if (dp[j-1] < v[i] && v[i] < dp[j]) @@ -10,6 +11,5 @@ int n; while (cin >> n) { } for (int i = 0; i <= n; i++) if (dp[i] == oo) dp[i] = -oo; - cout << max_element(dp.begin(), - dp.begin()+n+1) - dp.begin() << "\n"; + return max_element(dp.begin(), dp.begin()+n+1) - dp.begin(); } diff --git a/fontes/meet.h b/fontes/meet.h new file mode 100644 index 0000000000000000000000000000000000000000..4c403e41253e54629fa1fa5d2237b4c04fbc0949 --- /dev/null +++ b/fontes/meet.h @@ -0,0 +1,17 @@ +int mitm(vector<int>& v, int x) { + int n = v.size(); + map<ll, int> sums; ll c = 0; + for (int ss = 0; ss < 1<<(n/2); ss++) { + ll s = 0; + for (int i = 0; i < n/2; i++) if (1<<i & ss) + s += v[i]; + if (s <= x) { sums[s]++; } + } + for (int ss = 0; ss < 1<<(n/2+n%2); ss++) { + ll s = 0; + for (int i = n/2; i < n; i++) if (1<<(i-n/2) & ss) + s += v[i]; + if (sums.count(x - s)) { c += sums[x - s]; } + } + return c; +} diff --git a/fontes/merge-sort.h b/fontes/merge-sort.h deleted file mode 100644 index 0fbd62d27442fca8ab109b55f62d24d00974b62b..0000000000000000000000000000000000000000 --- a/fontes/merge-sort.h +++ /dev/null @@ -1,29 +0,0 @@ -vector<int> v (1e4); - -int merge_sort(int a, int b) { - // already sorted - if (a+1 == b) { return 0; } - - int swaps = 0; - - int m = a+(b-a)/2; - swaps += merge_sort(a, m); - swaps += merge_sort(m, b); - - vector<int> aux (b - a); - int f = a, s = m; - for (int i = 0; i < b - a; i++) { - if (s < b && f < m && v[f] > v[s]) { - // inversion - swaps += m-f; - } - if ((!(s < b) || v[f] < v[s]) && f < m) { - aux[i] = v[f++]; - } else { - aux[i] = v[s++]; - } - } - - copy(aux.begin(), aux.end(), v.begin()+a); - return swaps; -} diff --git a/fontes/mergesort.h b/fontes/mergesort.h new file mode 100644 index 0000000000000000000000000000000000000000..b13da7ac8043b6591fc42db8ceb317ac58204343 --- /dev/null +++ b/fontes/mergesort.h @@ -0,0 +1,17 @@ +int swaps = 0; +void merge_sort(int l, int r) { + if (r - l == 1) { return; } + int mi = l + (r - l) / 2; + merge_sort(l, mi); merge_sort(mi, r); + vector<int> aux (r - l); + int i = l, j = mi; + for (int k = 0; k < r - l; k++) { + if (i < mi && j < r) { + if (!(a[i] < a[j])) { swaps += mi - i; } + if (a[i] < a[j]) { aux[k] = a[i++]; } + else { aux[k] = a[j++]; } + } else if (i < mi) { aux[k] = a[i++]; } + else { aux[k] = a[j++]; } + } + copy(aux.begin(), aux.end(), a.begin()+l); +} diff --git a/fontes/miller-rabin.h b/fontes/miller-rabin.h index 783e61e7d901c3f23094d27441065234f76afd54..e14a42079721c6f60053bda7d1a5207ea61b0bd8 100644 --- a/fontes/miller-rabin.h +++ b/fontes/miller-rabin.h @@ -1,5 +1,4 @@ -using ll = long long; using i128 = __int128_t; - +using i128 = __int128_t; ll binary_pow(ll a, ll e, ll m) { if (e == 0) { return 1; } if (e == 1) { return a; } @@ -10,10 +9,7 @@ ll binary_pow(ll a, ll e, ll m) { } vector<int> witnesses = { - // primes from 2 to 37, enough for 64 bits - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 -}; - + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 }; bool is_prime(ll n) { if (n < 2) { return false; } int s = __lg((n-1)&-(n-1)); diff --git a/fontes/mo.h b/fontes/mo.h new file mode 100644 index 0000000000000000000000000000000000000000..e6dad023cb749f5dc5c9e4dd3affe2f0fb480394 --- /dev/null +++ b/fontes/mo.h @@ -0,0 +1,17 @@ +vector<int> mo(vector<qry> qs) { + vector<int> ans (qs.size()); + sort(qs.begin(), qs.end(), [](qry a, qry b) { + if (a.l/B != b.l/B) + return make_pair(a.l, a.r) < make_pair(b.l, b.r); + return (a.l/B) % 2 ? a.r < b.r : a.r > b.r; + }); + int l = 0, r = -1; + for (qry q : qs) { + while (l > q.l) { l--; ins(l, 'l'); } + while (r < q.r) { r++; ins(r, 'r'); } + while (l < q.l) { rem(l, 'l'); l++; } + while (r > q.r) { rem(r, 'r'); r--; } + ans[q.ix] = get_ans(); + } + return ans; +} diff --git a/fontes/mode.h b/fontes/mode.h new file mode 100644 index 0000000000000000000000000000000000000000..ed9fa540cc2f03f5a16d7024aa93f839520859ee --- /dev/null +++ b/fontes/mode.h @@ -0,0 +1,15 @@ +vector<int> v (N), freqfreq (N), freq (N); +int ans = 0; +void ins(int i, char dir) { + freqfreq[freq[v[i]]]--; + freq[v[i]]++; + freqfreq[freq[v[i]]]++; + if (freqfreq[ans+1]) { ans++; } +} +void rem(int i, char dir) { + freqfreq[freq[v[i]]]--; + freq[v[i]]--; + freqfreq[freq[v[i]]]++; + if (ans > 0 && freqfreq[ans] == 0) { ans--; } +} +int get_ans() { return ans; } diff --git a/fontes/neighbors.cpp b/fontes/neighbors.cpp deleted file mode 100644 index 44eb476c932bd8ca8d37a08b50ed7ea3504773ba..0000000000000000000000000000000000000000 --- a/fontes/neighbors.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// 4 neighbors -vector<int> dxy = { +1, 0, -1, 0, +1 }; -for (int k = 0; k < 4; k++) { - int di = dxy[k], dj = dxy[k+1]; - cout << di << " " << dj << "\n"; -} - -// 8 neighbors -for (int di : { -1, 0, +1 }) { -for (int dj : { -1, 0, +1 }) { - if (di == 0 && dj == 0) { continue; } - cout << di << " " << dj << "\n"; -} -} diff --git a/fontes/parquet.h b/fontes/parquet.h new file mode 100644 index 0000000000000000000000000000000000000000..d349155f0d759647516873b93b405f9ebdad42c4 --- /dev/null +++ b/fontes/parquet.h @@ -0,0 +1,21 @@ +vector<vector<ll>> dp (N+1, vector<ll>(1LL<<M)); + +void calc(int x = 0, int y = 0, int s = 0, int nxts = 0) { + if (x == n) { return; } + if (y >= m) { dp[x+1][nxts] += dp[x][s]; return; } + int cs = 1 << y; + if (s & cs) { calc(x, y+1, s, nxts); } + else { + calc(x, y+1, s, nxts | cs); + if (y+1 < m && ! (s & cs) && ! (s & (cs << 1))) + calc(x, y+2, s, nxts); + } +} + +int solve() { + dp[0][0] = 1; + for (int x = 0; x < n; x++) + for (int s = 0; s < (1<<m); s++) + calc(x, 0, s, 0); + return dp[n][0]; +} diff --git a/fontes/queens.h b/fontes/queens.h new file mode 100644 index 0000000000000000000000000000000000000000..bda2ad23744846b8c335a69327bfb7df7582ed7d --- /dev/null +++ b/fontes/queens.h @@ -0,0 +1,9 @@ +int n, s; +void queens(int i, ll rw = 0, ll ld = 0, ll rd = 0) { + if (rw == (1<<n)-1) { s++; return; } + ll pos = ((1<<n)-1) & (~(rw | ld | rd)); + while (pos) { + ll p = pos & -pos; pos -= p; + queens(i+1, rw | p, (ld | p) << 1, (rd | p) >> 1); + } +} diff --git a/fontes/remove.h b/fontes/remove.h new file mode 100644 index 0000000000000000000000000000000000000000..84d9ef568152358349d0f2fd3bfb84da25b066f9 --- /dev/null +++ b/fontes/remove.h @@ -0,0 +1,20 @@ +list<int> l; vector<int> bsz (N/B + 1); +vector<list<int>::iterator> bbegin (N/B + 1); +vector<int> remove(vector<int>& v, vector<int>& r) { + vector<int> ans; + int n = v.size(); + for (int i = 0; i < n; i++) { + auto ins = l.insert(l.end(), v[i]); + if (i % B == 0) { bbegin[i/B] = ins; } + bsz[i/B]++; + } + for (int i : r) { + auto it = bbegin[i/B]; advance(it, i%B); + if (i % B == 0) { bbegin[i/B]++; } + ans.push_back(*it); l.erase(it); + int bi = i/B; + while (bsz[bi+1] > 0) { bbegin[bi+1]++; bi++; } + bsz[bi]--; + } + return ans; +} diff --git a/fontes/removedeque.h b/fontes/removedeque.h new file mode 100644 index 0000000000000000000000000000000000000000..68394aaf90235a83467044a4d8810065cc3bed7a --- /dev/null +++ b/fontes/removedeque.h @@ -0,0 +1,18 @@ +vector<deque<int>> l (N/B + 1); +vector<int> remove(vector<int>& v, vector<int>& r) { + vector<int> ans; + int n = v.size(); + for (int i = 0; i < n; i++) + l[i/B].push_back(v[i]); + for (int i : r) { + auto it = l[i/B].begin()+(i%B); + ans.push_back(*it); l[i/B].erase(it); + int bi = i/B; + while (l[bi+1].size() > 0) { + l[bi+1].push_back(l[bi].back()); + l[bi].pop_back(); + bi++; + } + } + return ans; +} diff --git a/fontes/sparse-table.h b/fontes/sparse-table.h new file mode 100644 index 0000000000000000000000000000000000000000..468ca54814e2f3118ac673d97603d939325be434 --- /dev/null +++ b/fontes/sparse-table.h @@ -0,0 +1,21 @@ +const int K = 25; +vector<int> lg (N+1); +vector<vector<int>> st (N, vector<int>(K+1)); + +void build(vector<int>& src) { + lg[1] = 0; + for (int i = 2; i <= N; i++) + lg[i] = lg[i/2] + 1; + + for (int i = 0; i < src.size(); i++) + st[i][0] = src[i]; + + for (int j = 1; j <= K; j++) + for (int i = 0; i + (1 << j) <= N; i++) + st[i][j] = min(st[i][j-1], st[i + (1 << (j - 1))][j - 1]); +} + +int min_inclusive(int l, int r) { + int j = lg[r - l + 1]; + return min(st[l][j], st[r - (1 << j) + 1][j]); +} diff --git a/fontes/stdt.h b/fontes/stdt.h index fb51d9c81d66c3ea8fac7679f8b9e213765bba81..b5b848b2c7f4ead1b7f4aa7545e53a9f1e1c0652 100644 --- a/fontes/stdt.h +++ b/fontes/stdt.h @@ -1,6 +1,5 @@ -vector<int> depth (N); -vector<int> up (N); vector<int> weiop (N); -vector<int> bup (N); vector<int> bweiop (N); +vector<int> up (N), bup (N), depth (N); +vector<ll> weiop (N), bweiop (N); void stdt_decompose(int u, int p, int w) { up[u] = p; weiop[u] = w; diff --git a/fontes/subsum.h b/fontes/subsum.h new file mode 100644 index 0000000000000000000000000000000000000000..675e4b8c27fded7e423cbb3179fd98773b33c6cc --- /dev/null +++ b/fontes/subsum.h @@ -0,0 +1,10 @@ +ii subsum(vector<int>& v, int s) { + int n = v.size(); + int i = 0, j = 1, w = v[0]; + while (j < n) { + while (w + v[j] > s && i < j-1) { w -= v[i++]; } + if (w < s) { w += v[j++]; } + if (w == s) { return {i, j}; } + } + return {-1,-1}; +}