diff --git a/caderno.pdf b/caderno.pdf index 4e30bc3034b81198fa337a28498df566ebab24b7..287710b2c0adc994f9a51831cf88226b60a60b5e 100644 Binary files a/caderno.pdf and b/caderno.pdf differ diff --git a/caderno/caderno.tex b/caderno/caderno.tex index fe3a092110df0585e85787fdd293b023c57d7d1b..69a50d616cbe191c20b4c08a34d7748fa7ec0f49 100644 --- a/caderno/caderno.tex +++ b/caderno/caderno.tex @@ -6,6 +6,7 @@ \usepackage[brazilian]{babel} \usepackage{lmodern} \usepackage{amsmath} +\usepackage{stfloats} \usepackage{caption} \usepackage{multirow} \usepackage{fontspec} @@ -25,11 +26,10 @@ \newcommand{\bigO}{\mathcal{O}} \lstset{ - numbers=left, - xleftmargin=\parindent, basicstyle=\footnotesize\ttfamily, showspaces=false, showstringspaces=false, + keepspaces=true, language=C++, columns=fullflexible, commentstyle=\color{commentgreen}, @@ -90,7 +90,7 @@ \maketitle \tableofcontents -\begin{table*} +\begin{table*}[bp] \centering \begin{tabular}{lll} \hline @@ -113,9 +113,28 @@ \newpage \section{Teoria} -\subsection{Comparações algorítmicas} -\begin{table}[ht] - \centering +\subsection{Limites numéricos} +\begin{center} + \begin{tabular}{crcccc} + \hline + Sinal & Tipo & Bits & Máximo & Dígitos \\ + \hline + $+/-$ & \texttt{char} & 8 & 127 & 2 \\ + $+$ & \texttt{char} & 8 & 255 & 2 \\ + $+/-$ & \texttt{short} & 16 & 32\,767 & 4 \\ + $+$ & \texttt{short} & 16 & 65\,535 & 4 \\ + $+/-$ & \texttt{int}/\texttt{long} & 32 & $\approx 2 \cdot 10^{9}$ & 9\\ + $+$ & \texttt{int}/\texttt{long} & 32 & $\approx 4 \cdot 10^{9}$ & 9 \\ + $+/-$ & \texttt{long long} & 64 & $\approx 9 \cdot 10^{18}$ & 18 \\ + $+$ & \texttt{long long} & 64 & $\approx 18 \cdot 10^{18}$ & 19 \\ + $+/-$ & \texttt{\_\_int128} & 128 & $\approx 17 \cdot 10^{37}$ & 38 \\ + $+$ & \texttt{\_\_int128} & 128 & $\approx 3 \cdot 10^{38}$ & 38 \\ + \hline + \end{tabular} +\end{center} + +\subsection{Comparações numéricas} +\begin{center} \begin{tabular}{l|r} \hline $\lg 10$ (\texttt{1E1}) & 2.3 \\ @@ -135,27 +154,45 @@ $2^{20}$ & $\approx 10^{6}$ \\ \hline \end{tabular} -\end{table} +\end{center} -\begin{table}[ht] - \centering - \begin{tabular}{crcccc} - \hline - Sinal & Tipo & Bits & Máximo & Dígitos \\ - \hline - $+/-$ & \texttt{char} & 8 & 127 & 2 \\ - $+$ & \texttt{char} & 8 & 255 & 2 \\ - $+/-$ & \texttt{short} & 16 & 32\,767 & 4 \\ - $+$ & \texttt{short} & 16 & 65\,535 & 4 \\ - $+/-$ & \texttt{int}/\texttt{long} & 32 & $\approx 2 \cdot 10^{9}$ & 9\\ - $+$ & \texttt{int}/\texttt{long} & 32 & $\approx 4 \cdot 10^{9}$ & 9 \\ - $+/-$ & \texttt{long long} & 64 & $\approx 9 \cdot 10^{18}$ & 18 \\ - $+$ & \texttt{long long} & 64 & $\approx 18 \cdot 10^{18}$ & 19 \\ - $+/-$ & \texttt{\_\_int128} & 128 & $\approx 17 \cdot 10^{37}$ & 38 \\ - $+$ & \texttt{\_\_int128} & 128 & $\approx 3 \cdot 10^{38}$ & 38 \\ - \hline - \end{tabular} -\end{table} +\subsection{Identidades binomiais} +\begin{align*} + \binom{n}{k} &= \binom{n-1}{k-1} + \binom{n-1}{k}, \forall n \ge 0 \wedge 0 \le k \le n \\ + \binom{n}{k} &= \frac{n!}{k!(n-k)!} +\end{align*} + +\subsection{Teorema de Lucas} +\begin{align*} + \binom{n}{m} = \Pi_{i=0}^{k} \binom{n_i}{m_i} \pmod{p} +\end{align*} +Para $p$ primo, $n_i$ e $m_i$ são coeficientes das representações de $n$ e $m$ na base $p$. + +\subsection{Números de Catalão} +{\sloppy +1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, +9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, +24466267020, 91482563640, \\343059613650, 1289904147324, 4861946401452, +\\18367353072152, 69533550916004, 263747951750360, \\1002242216651368.} + +\begin{align*} + C_n = \frac{1}{n+1} \binom{2n}{n} = \frac{(2n)!}{(n+1)!n!} = \Pi^n_{k=2} \frac{n+k}{k}, n \ge 0. +\end{align*} + +Aplicações: +\begin{itemize} + \itemsep -2pt + \item $C_n$ é o número de expressões contendo $n$ parênteses corretamente pareados. + \item $C_n$ é o número de árvores binárias completas com $n+1$ folhas. + \item $C_n$ são as vezes que um polígono convexo com $n+2$ lados pode ser cortado em triângulos conectando os vérticese com linhas retas. +\end{itemize} + +\subsection{Fórmula de Heron} +A área de um triângulo pode ser escrita como +\begin{align*} + A = \sqrt{s(s-a)(s-b)(s-c)} +\end{align*} +onde $s = \frac{a+b+c}{2}$. \subsection{Progressões} \begin{align*} @@ -172,18 +209,6 @@ S_n = \frac{a_1(q^n - 1)}{q-1} \end{align*} -\subsection{Identidades binomiais} -\begin{align*} - \binom{n}{k} &= \binom{n-1}{k-1} + \binom{n-1}{k}, \forall n \ge 0 \wedge 0 \le k \le n \\ - \binom{n}{k} &= \frac{n!}{k!(n-k)!} -\end{align*} - -\subsection{Teorema de Lucas} -\begin{align*} - \binom{n}{m} = \Pi_{i=0}^{k} \binom{n_i}{m_i} \pmod{p} -\end{align*} -Para $p$ primo, $n_i$ e $m_i$ são coeficientes das representações de $n$ e $m$ na base $p$. - \subsection{Teoremas de Fermat} \begin{align*} a^p = a \pmod{p} \\ @@ -199,13 +224,6 @@ onde $p$ é primo. \end{align*} para $a$ e $m$ coprimos. -\subsection{Fórmula de Heron} -A área de um triângulo pode ser escrita como -\begin{align*} - A = \sqrt{s(s-a)(s-b)(s-c)} -\end{align*} -onde $s = \frac{a+b+c}{2}$. - \subsection{Séries} \begin{align*} @@ -228,41 +246,22 @@ onde $s = \frac{a+b+c}{2}$. \end{itemize} \end{multicols} -\subsection{Números de Catalão} -{\sloppy -1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, -9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, -24466267020, 91482563640, \\343059613650, 1289904147324, 4861946401452, -\\18367353072152, 69533550916004, 263747951750360, \\1002242216651368.} - -\begin{align*} - C_n = \frac{1}{n+1} \binom{2n}{n} = \frac{(2n)!}{(n+1)!n!} = \Pi^n_{k=2} \frac{n+k}{k}, n \ge 0. -\end{align*} - -Aplicações: -\begin{itemize} - \itemsep -2pt - \item $C_n$ é o número de expressões contendo $n$ parênteses corretamente pareados. - \item $C_n$ é o número de árvores binárias completas com $n+1$ folhas. - \item $C_n$ são as vezes que um polígono convexo com $n+2$ lados pode ser cortado em triângulos conectando os vérticese com linhas retas. -\end{itemize} - \section{C++} \subsection{Esboço} -\lstinputlisting{fontes/template.cpp} +\lstinputlisting{fontes-com-hash/template.cpp} \subsection{Teste de estresse} -\lstinputlisting[language=bash]{fontes/stress.sh} +\lstinputlisting[language=bash]{fontes-com-hash/stress.sh} \subsection{Hash de linhas em $[l, r]$} -\lstinputlisting[language=bash]{fontes/hash.sh} +\lstinputlisting[language=bash]{fontes-com-hash/hash.sh} \subsection{vimrc} -\lstinputlisting{fontes/vimrc} +\lstinputlisting{fontes-com-hash/vimrc} \subsection{Gerador} -\lstinputlisting{fontes/gen.cpp} +\lstinputlisting{fontes-com-hash/gen.cpp} \section{Estrutura de Dados} \subsection{União-busca} -\lstinputlisting{fontes/disjoint.h} +\lstinputlisting{fontes-com-hash/disjoint.h} \subsection{Árvore de Fenwick} \begin{tabular}{l|l|l} @@ -283,7 +282,7 @@ Aplicações: \hline \end{tabular} -\lstinputlisting{fontes/fenwick-tree.h} +\lstinputlisting{fontes-com-hash/fenwick-tree.h} \subsection{Árvore de Fenwick 2D} \begin{tabular}{l|l|l} @@ -294,7 +293,7 @@ Aplicações: \hline \end{tabular} -\lstinputlisting{fontes/fenwick-2d-tree.h} +\lstinputlisting{fontes-com-hash/fenwick-2d-tree.h} \subsection{Árvore de Fenwick intervalar} \begin{tabular}{l|l|l} @@ -305,40 +304,21 @@ Aplicações: \hline \end{tabular} -\lstinputlisting{fontes/fenwick-range-tree.h} +\lstinputlisting{fontes-com-hash/fenwick-range-tree.h} \subsection{Tabela esparsa} -\lstinputlisting{fontes/sparse-table.h} +\lstinputlisting{fontes-com-hash/sparse-table.h} \subsection{Pilha mínima} -\lstinputlisting{fontes/min-stack.h} - -\subsection{Maior elemento anterior} -\lstinputlisting{fontes/previous-greater-element.h} - -\subsection{Menor elemento anterior} -\lstinputlisting{fontes/previous-lesser-element.h} +\lstinputlisting{fontes-com-hash/min-stack.h} \subsection{Próximo maior elemento} -\lstinputlisting{fontes/next-greater-element.h} - -\subsection{Próximo menor elemento} -\lstinputlisting{fontes/next-lesser-element.h} - -\subsection{Fila mínima (sabendo o que remover)} -\lstinputlisting{fontes/min-queue.h} +\lstinputlisting{fontes-com-hash/next-greater-element.h} \subsection{Fila mínima} -\lstinputlisting{fontes/min-queue-2.h} - -\subsection{Fila mínima (guarda os elementos)} -\lstinputlisting{fontes/min-queue-3.h} - -\subsection{Hash customizado} -\lstinputlisting{fontes/custom-hash.h} +\lstinputlisting{fontes-com-hash/min-queue.h} \subsection{Árvore de segmentos iterativa} - \vspace{4pt} \noindent \footnotesize @@ -350,37 +330,40 @@ Aplicações: \texttt{FACTOR} & \texttt{(tb - ta + 1)} & \texttt{1} & \texttt{1} \\ \hline \end{tabular} - -\lstinputlisting{fontes/segment-tree.h} +\lstinputlisting{fontes-com-hash/segment-tree.h} \subsection{Árvore de segmentos preguiçosa iter.} -\lstinputlisting{fontes/lazy-segment-tree.h} +\lstinputlisting{fontes-com-hash/lazy-segment-tree.h} -\subsection{Árvore de segmentos recursiva} -\lstinputlisting{fontes/recursive-segment-tree.h} +\subsection{Hash customizado} +\lstinputlisting{fontes-com-hash/custom-hash.h} -\subsection{Conjunto de intervalos coloridos} -\lstinputlisting{fontes/interval-set.h} +\subsection{Árvore de segmentos recursiva} +\lstinputlisting{fontes-com-hash/recursive-segment-tree.h} \subsection{Árvore de segmentos preguiçosa rec.} -\lstinputlisting{fontes/recursive-lazy-segment-tree.h} +\lstinputlisting{fontes-com-hash/recursive-lazy-segment-tree.h} + +\subsection{Conjunto de intervalos coloridos} +\lstinputlisting{fontes-com-hash/interval-set.h} \section{Grafos} \subsection{Articulações e pontes} -\lstinputlisting{fontes/articulations-bridges.h} +\lstinputlisting{fontes-com-hash/articulations-bridges.h} +\clearpage \subsection{Componentes fortes -- Tarjan} -\lstinputlisting{fontes/tarjan.h} +\lstinputlisting{fontes-com-hash/tarjan.h} \subsection{Componentes fortes -- Kosaraju} -\lstinputlisting{fontes/kosaraju.h} +\lstinputlisting{fontes-com-hash/kosaraju.h} \subsection{Ordenação topológica} -\lstinputlisting{fontes/topological-order.h} +\lstinputlisting{fontes-com-hash/topological-order.h} \subsection{Busca em largura 0-1} -\lstinputlisting{fontes/bfs-01.h} +\lstinputlisting{fontes-com-hash/bfs-01.h} \subsection{Emparelhamento estável} \begin{tabular}{l} @@ -388,55 +371,51 @@ Aplicações: $\bigO(n^2)$ \\ \hline \end{tabular} -\lstinputlisting{fontes/stable-matching.h} +\lstinputlisting{fontes-com-hash/stable-matching.h} \subsection{Caminho euleriano} -\lstinputlisting{fontes/eulerian-path.h} +\lstinputlisting{fontes-com-hash/eulerian-path.h} -\subsection{Caminho mínimo -- Dijkstra} -\lstinputlisting{fontes/dijkstra.h} +\clearpage -\subsection{Caminho mínimo -- Bellman-Ford} -\lstinputlisting{fontes/bellman-ford.h} - -\subsection{Caminho mínimo -- SPFA} -\lstinputlisting{fontes/spfa.h} +\subsection{Stoer-Wagner} +\lstinputlisting{fontes-com-hash/stoer-wagner.h} -\subsection{Caminhos mínimos -- Floyd-Warshall} -\lstinputlisting{fontes/floyd-warshall.h} +\subsection{Menor no maior} +\lstinputlisting{fontes-com-hash/small-to-large.h} \subsection{Árvore geradora mínima -- Prim} -\lstinputlisting{fontes/prim.h} +\lstinputlisting{fontes-com-hash/prim.h} \subsection{Árvore geradora mínima -- Kruskal} -\lstinputlisting{fontes/kruskal.h} +\lstinputlisting{fontes-com-hash/kruskal.h} -\subsection{Stoer-Wagner} -\lstinputlisting{fontes/stoer-wagner.h} +\subsection{Caminho mínimo -- Dijkstra} +\lstinputlisting{fontes-com-hash/dijkstra.h} + +\subsection{Caminho mínimo -- Bellman-Ford} +\lstinputlisting{fontes-com-hash/bellman-ford.h} + +\subsection{Caminho mínimo -- SPFA} +\lstinputlisting{fontes-com-hash/spfa.h} + +\subsection{Caminhos mínimos -- Floyd-Warshall} +\lstinputlisting{fontes-com-hash/floyd-warshall.h} \subsection{Fluxo máximo} -\lstinputlisting{fontes/ford-fulkerson-edmons-karp.h} +\lstinputlisting{fontes-com-hash/ford-fulkerson-edmons-karp.h} \subsection{Fluxo de custo mínimo} -\lstinputlisting{fontes/ford-fulkerson-edmons-karp-min-cost.h} +\lstinputlisting{fontes-com-hash/ford-fulkerson-edmons-karp-min-cost.h} \subsection{Fluxo máximo Dinic} -\lstinputlisting{fontes/dinic.h} - -\subsection{Menor no maior} -\lstinputlisting{fontes/small-to-large.h} +\lstinputlisting{fontes-com-hash/dinic.h} \subsection{Ascensão binária} -\lstinputlisting{fontes/binary-lifting.h} +\lstinputlisting{fontes-com-hash/binary-lifting.h} \subsection{Menor anc. comum -- Ancensão binária} -\lstinputlisting{fontes/lca-binary-lifting.h} - -\subsection{Menor anc. comum -- Offline} -\lstinputlisting{fontes/lca-offline.h} - -\subsection{Decomposição centróide} -\lstinputlisting{fontes/centroid.h} +\lstinputlisting{fontes-com-hash/lca-binary-lifting.h} \subsection{Decomposição pesado-leve} \begin{tabular}{l|l} @@ -451,10 +430,18 @@ Aplicações: Atualização/Consulta $\bigO(\lg^2 n)$ \\ \hline \end{tabular} -\lstinputlisting{fontes/hld.h} +\lstinputlisting{fontes-com-hash/hld.h} \subsection{Decomposição pesado-leve -- K-ésimo} -\lstinputlisting{fontes/hld-kth.h} +\lstinputlisting{fontes-com-hash/hld-kth.h} + +\clearpage + +\subsection{Menor anc. comum -- Offline} +\lstinputlisting{fontes-com-hash/lca-offline.h} + +\subsection{Decomposição centróide} +\lstinputlisting{fontes-com-hash/centroid.h} \subsection{Empar. máximo bipartido -- Kuhn} \begin{tabular}{l} @@ -462,75 +449,83 @@ Aplicações: As partes tem enumerações distintas \\ \hline \end{tabular} -\lstinputlisting{fontes/kuhn.h} +\lstinputlisting{fontes-com-hash/kuhn.h} \subsection{Decomposição raiz quadrada de árvore} -\lstinputlisting{fontes/tree-square-root-decomposition.h} +\lstinputlisting{fontes-com-hash/tree-square-root-decomposition.h} \subsection{Menor anc. comum -- Dec. raiz quad.} -\lstinputlisting{fontes/lca-square-root-decomposition.h} +\lstinputlisting{fontes-com-hash/lca-square-root-decomposition.h} \section{Matemática} \subsection{Operações comuns} -\lstinputlisting{fontes/numbers.h} +\lstinputlisting{fontes-com-hash/numbers.h} \subsection{Inteiro modular} -\lstinputlisting{fontes/modular-integer.h} +\lstinputlisting{fontes-com-hash/modular-integer.h} \subsection{Matriz} -\lstinputlisting{fontes/matrix.h} +\lstinputlisting{fontes-com-hash/matrix.h} \subsection{Distribuição binomial} A probabilidade do evento $X$ acontecer $k$ vezes é dada por \begin{align*} Pr(X = k) = \binom{n}{k}p^k (1 - p)^{n-k} \end{align*} -\lstinputlisting{fontes/binomial-distribution.h} +\lstinputlisting{fontes-com-hash/binomial-distribution.h} \subsection{Integração pelo método de Simpson} -\lstinputlisting{fontes/simpson-integration.h} +\lstinputlisting{fontes-com-hash/simpson-integration.h} \subsection{Sequência de Bruijn} Número de sequências distintas: \begin{align*} \frac{(k!)^{k^{n-1}}}{k^n} \end{align*} -\lstinputlisting{fontes/bruijn.h} - -\subsection{Truque de divisão} -Gera um conjunto $n/i$ para todo $i$ em $\bigO(\sqrt{n})$. -\lstinputlisting{fontes/division-trick.h} +\lstinputlisting{fontes-com-hash/bruijn.h} \subsection{PD de Dígito} -\lstinputlisting{fontes/digit-dp.h} +\lstinputlisting{fontes-com-hash/digit-dp.h} -\subsection{Compressão de coordenadas} -\lstinputlisting{fontes/coordinate-compression.h} +\subsection{Primeiros digitos de $n^k$} +\lstinputlisting{fontes-com-hash/nk-first-digits.h} \subsection{Problema de Josephus} -\lstinputlisting{fontes/josephus.h} - -\subsection{Primeiros digitos de $n^k$} -\lstinputlisting{fontes/nk-first-digits.h} +\lstinputlisting{fontes-com-hash/josephus.h} \subsection{2-SAT} -\lstinputlisting{fontes/2-sat.h} +\lstinputlisting{fontes-com-hash/2-sat.h} + +\subsection{Truque de divisão} +Gera um conjunto $n/i$ para todo $i$ em $\bigO(\sqrt{n})$. +\lstinputlisting{fontes-com-hash/division-trick.h} + +\subsection{Multiplicação -- Karatsuba} +\begin{tabular}{l} + \hline + $\bigO(n^{\log_3 n})$ \\ +\hline +\end{tabular} +\lstinputlisting{fontes-com-hash/karatsuba.h} + +\subsection{Compressão de coordenadas} +\lstinputlisting{fontes-com-hash/coordinate-compression.h} \subsection{Inclusão-Exclusão} -\lstinputlisting{fontes/inclusion-exclusion.h} +\lstinputlisting{fontes-com-hash/inclusion-exclusion.h} \subsection{Mínimo excluído com conjunto} -\lstinputlisting{fontes/mexset.h} +\lstinputlisting{fontes-com-hash/mexset.h} \subsection{Mínimo excluído} -\lstinputlisting{fontes/mex.h} +\lstinputlisting{fontes-com-hash/mex.h} \subsection{Nímero (Números de Grundy)} -\lstinputlisting{fontes/grundy.h} +\lstinputlisting{fontes-com-hash/grundy.h} \subsection{Jogo de Nim} -\lstinputlisting{fontes/nim.h} +\lstinputlisting{fontes-com-hash/nim.h} \subsection{Euclides estendido/inv. multiplicativo} \begin{tabular}{l} @@ -543,27 +538,19 @@ $\bigO(\lg \min(a, b))$ \\ ax &= gcd(a, b) \pmod{b} \\ (\gcd(a, b) = 1) &\implies (ax = 1 \pmod{b}) \end{align*} -\lstinputlisting{fontes/extended-euclidean.h} +\lstinputlisting{fontes-com-hash/extended-euclidean.h} + +\subsection{Números de Catalão} +\lstinputlisting{fontes-com-hash/catalan.h} \subsection{Detecção de ciclo} -\lstinputlisting{fontes/floyd.h} +\lstinputlisting{fontes-com-hash/floyd.h} \subsection{Equação diofantina linear} \begin{align*} ax + by = c \end{align*} -\lstinputlisting{fontes/diophantine.h} - -\subsection{Multiplicação -- Karatsuba} -\begin{tabular}{l} - \hline - $\bigO(n^{\log_3 n})$ \\ -\hline -\end{tabular} -\lstinputlisting{fontes/karatsuba.h} - -\subsection{Números de Catalão} -\lstinputlisting{fontes/catalan.h} +\lstinputlisting{fontes-com-hash/diophantine.h} \subsection{Fatoração por tentativa} \begin{tabular}{l} @@ -571,7 +558,7 @@ ax + by = c $\bigO(\sqrt{n})$ \\ \hline \end{tabular} -\lstinputlisting{fontes/factorize.h} +\lstinputlisting{fontes-com-hash/factorize.h} \subsection{Crivo de Eratóstenes} \begin{tabular}{l} @@ -579,7 +566,7 @@ ax + by = c $\bigO(n \lg\lg n)$ \\ \hline \end{tabular} -\lstinputlisting{fontes/sieve.h} +\lstinputlisting{fontes-com-hash/sieve.h} \subsection{Totiente de Euler} \begin{tabular}{l} @@ -587,16 +574,16 @@ ax + by = c $\bigO(n \lg \lg n)$ \\ \hline \end{tabular} -\lstinputlisting{fontes/euler-totient.h} +\lstinputlisting{fontes-com-hash/euler-totient.h} \subsection{Eliminação gaussiana} -\lstinputlisting{fontes/gauss.h} +\lstinputlisting{fontes-com-hash/gauss.h} \subsection{Exponenciação binária} -\lstinputlisting{fontes/binary-pow.h} +\lstinputlisting{fontes-com-hash/binary-pow.h} \subsection{Miller-Rabin} -\lstinputlisting{fontes/miller-rabin.h} +\lstinputlisting{fontes-com-hash/miller-rabin.h} \subsection{Pollard Rho} \begin{tabular}{l} @@ -604,7 +591,7 @@ ax + by = c $\bigO(n^{1/4})$ \\ \hline \end{tabular} -\lstinputlisting{fontes/pollard-rho.h} +\lstinputlisting{fontes-com-hash/pollard-rho.h} \subsection{Teorema chinês do resto} \begin{tabular}{l} @@ -612,7 +599,7 @@ ax + by = c $\bigO(t \lg(m_1 m_2 \ldots m_t))$ \\ \hline \end{tabular} -\lstinputlisting{fontes/chinese-remainder-theorem.h} +\lstinputlisting{fontes-com-hash/chinese-remainder-theorem.h} \subsection{Teorema chinês do resto generalizado} \begin{tabular}{l|l} @@ -621,7 +608,7 @@ ax + by = c Infinitas soluções $\pm \text{lcm}(m_1m_2\ldots m_t)$ \\ \hline \end{tabular} -\lstinputlisting{fontes/generalized-chinese-remainder-theorem.h} +\lstinputlisting{fontes-com-hash/generalized-chinese-remainder-theorem.h} \section{Strings} @@ -632,153 +619,155 @@ ax + by = c Busca $\bigO(n + m)$ \\ \hline \end{tabular} -\lstinputlisting{fontes/kmp.h} +\lstinputlisting{fontes-com-hash/kmp.h} \subsection{Algoritmo Z} $z[i]$ é o tamanho da maior string que é ao mesmo tempo, um prefixo de $s$ e um prefixo do sufixo de $s$ começando em $i$. -\lstinputlisting{fontes/z.h} +\lstinputlisting{fontes-com-hash/z.h} \subsection{String Hashing} -\lstinputlisting{fontes/string-hash.h} +\lstinputlisting{fontes-com-hash/string-hash.h} \subsection{Autômato KMP} -\lstinputlisting{fontes/kmp-automaton.h} +\lstinputlisting{fontes-com-hash/kmp-automaton.h} -\subsection{Trie} -\lstinputlisting{fontes/trie.h} +\subsection{Autômato de Sufixo} +\lstinputlisting{fontes-com-hash/suffix-automaton.h} -\subsection{Aho-Corasick} -\lstinputlisting{fontes/aho-corasick.h} +\subsection{Aho-Corasick/Trie} +\lstinputlisting{fontes-com-hash/aho-corasick.h} -\subsection{Árvore de sufixos} -\lstinputlisting{fontes/suffix-tree.h} +\subsection{Vetor de sufixos radix} +\lstinputlisting{fontes-com-hash/suffix-array-radix.h} \subsection{Vetor de sufixos} -\lstinputlisting{fontes/suffix-array.h} - -\subsection{Vetor de sufixos radix} -\lstinputlisting{fontes/suffix-array-radix.h} +\lstinputlisting{fontes-com-hash/suffix-array.h} -\subsection{Autômato de Sufixo} -\lstinputlisting{fontes/suffix-automaton.h} +\subsection{Árvore de sufixos} +\lstinputlisting{fontes-com-hash/suffix-tree.h} \section{Geometria} \subsection{Pontos} -\lstinputlisting{fontes/point.h} +\lstinputlisting{fontes-com-hash/point.h} -\subsection{Fecho convexo com corrente monotônica} +\subsection{Fecho convexo de Graham} \begin{tabular}{l} \hline $\bigO(n \lg n)$ \\ \hline \end{tabular} -\lstinputlisting{fontes/monotone.h} +\lstinputlisting{fontes-com-hash/graham.h} -\subsection{Fecho convexo de Graham} +\subsection{Fecho convexo com corrente monotônica} \begin{tabular}{l} \hline $\bigO(n \lg n)$ \\ \hline \end{tabular} -\lstinputlisting{fontes/graham.h} +\lstinputlisting{fontes-com-hash/monotone.h} + +\subsection{Árvore KD} +\lstinputlisting{fontes-com-hash/kd-tree.h} \subsection{Ponto dentro do polígono?} -\lstinputlisting{fontes/point-in-polygon.h} +\lstinputlisting{fontes-com-hash/point-in-polygon.h} \subsection{Ponto dentro do polígono convexo?} -\lstinputlisting{fontes/point-in-convex-polygon.h} +\lstinputlisting{fontes-com-hash/point-in-convex-polygon.h} \subsection{Área de polígono} -\lstinputlisting{fontes/polygon-area.h} +\lstinputlisting{fontes-com-hash/polygon-area.h} \subsection{Pontos inteiros no polígono} \begin{align*} A = i + b/2 - 1 \end{align*} -\lstinputlisting{fontes/polygon-lattice-points.h} +\lstinputlisting{fontes-com-hash/polygon-lattice-points.h} \subsection{Segmento} -\lstinputlisting{fontes/segment.h} +\lstinputlisting{fontes-com-hash/segment.h} \subsection{Ponto e segmento} -\lstinputlisting{fontes/point-in-seg.h} +\lstinputlisting{fontes-com-hash/point-in-seg.h} + +\subsection{Manhattan máximo} +\lstinputlisting{fontes-com-hash/manhattan.h} + +\subsection{Voronoi} +\lstinputlisting{fontes-com-hash/voronoi.h} \subsection{Varredura angular} -\lstinputlisting{fontes/angular-sweep.h} +\lstinputlisting{fontes-com-hash/angular-sweep.h} \subsection{Interseção de retângulos} -\lstinputlisting{fontes/rectangle-intersection.h} +\lstinputlisting{fontes-com-hash/rectangle-intersection.h} \subsection{Segmento e segmento} -\lstinputlisting{fontes/segment-vs-segment.h} - -\subsection{Árvore KD} -\lstinputlisting{fontes/kd-tree.h} - -\subsection{Distância de Manhattan máxima entre dois pontos} -\lstinputlisting{fontes/manhattan.h} +\lstinputlisting{fontes-com-hash/segment-vs-segment.h} \section{Algoritmos} -\subsection{Ordenação por fusão} -\lstinputlisting{fontes/merge-sort.h} +\subsection{Maior subsequência crescente rápido} +\lstinputlisting{fontes-com-hash/longest-increasing-subsequence-n-lg-n.h} \subsection{Subconjuntos de tamanho $K$} -\lstinputlisting{fontes/next-combination.h} - -\subsection{Agendamento ótimo de tarefas} -\lstinputlisting{fontes/optimal-schedule-jobs.h} +\lstinputlisting{fontes-com-hash/next-combination.h} \subsection{Soma sobre subconjuntos} \begin{align*} f[m] = \sum_{i \subseteq m} a[i] \end{align*} -Para mudar para superconjunto, use \texttt{~mask} no if. -\lstinputlisting{fontes/sos.h} +Para mudar para superconjunto, use \texttt{\~{}mask} no if. +\lstinputlisting{fontes-com-hash/sos.h} + +\subsection{Ordenação por fusão} +\lstinputlisting{fontes-com-hash/merge-sort.h} + +\subsection{Agendamento ótimo de tarefas} +\lstinputlisting{fontes-com-hash/optimal-schedule-jobs.h} \subsection{Algoritmo de Mo} -\lstinputlisting{fontes/mo-algorithm.h} +\lstinputlisting{fontes-com-hash/mo-algorithm.h} \subsection{Meet in the middle} -\lstinputlisting{fontes/meet-in-the-middle.h} +\lstinputlisting{fontes-com-hash/meet-in-the-middle.h} \subsection{Maior subsequência comum} -\lstinputlisting{fontes/longest-common-subsequence.h} - -\subsection{Maior subsequência crescente rápido} -\lstinputlisting{fontes/longest-increasing-subsequence-n-lg-n.h} +\lstinputlisting{fontes-com-hash/longest-common-subsequence.h} \subsection{PD de perfil quebrado} -\lstinputlisting{fontes/parquet.h} +\lstinputlisting{fontes-com-hash/parquet.h} \subsection{Submáscaras} -\lstinputlisting{fontes/submasks.h} +\lstinputlisting{fontes-com-hash/submasks.h} \section{Problemas} -\subsection{Rainhas no tabuleiro} -\lstinputlisting{fontes/queens.h} +\subsection{Frequência de frequências/moda com Mo} +\lstinputlisting{fontes-com-hash/freq-freq-mode.h} -\subsection{Frequência de frequências/Moda usando Mo} -\lstinputlisting{fontes/freq-freq-mode.h} +\clearpage -\subsection{Inversões usando algoritmo de Mo} -\lstinputlisting{fontes/inversion-mo.h} +\subsection{Rainhas no tabuleiro} +\lstinputlisting{fontes-com-hash/queens.h} \subsection{Remoção de valores com deque} -\lstinputlisting{fontes/remove-deque.h} +\lstinputlisting{fontes-com-hash/remove-deque.h} + +\subsection{Inversões usando algoritmo de Mo} +\lstinputlisting{fontes-com-hash/inversion-mo.h} \subsection{Desembarcadouro} -\lstinputlisting{fontes/desembarcadouro.h} +\lstinputlisting{fontes-com-hash/desembarcadouro.h} \subsection{Média e mediana} -\lstinputlisting{fontes/mean-median.h} +\lstinputlisting{fontes-com-hash/mean-median.h} \subsection{Distância de edição} -\lstinputlisting{fontes/edit-distance.h} +\lstinputlisting{fontes-com-hash/edit-distance.h} \subsection{Código de Gray} -\lstinputlisting{fontes/gray-code.h} +\lstinputlisting{fontes-com-hash/gray-code.h} \end{document} diff --git a/fontes/aho-corasick.h b/fontes/aho-corasick.h index 595163efafec97fb8abb7b8c9184331ff68c1fe5..02c8662c6ccc950fcbcf25ffe6c74dad242694b1 100644 --- a/fontes/aho-corasick.h +++ b/fontes/aho-corasick.h @@ -8,8 +8,7 @@ struct node { vector<node> aca (1); void ins(string ne, int ix) { - int u = 0; - for (int i = 0; i < ne.size(); i++) { + int u = 0; for (int i = 0; i < ne.size(); i++) { int ch = to_i(ne[i]); if (aca[u].nxt[ch] == -1) { aca[u].nxt[ch] = aca.size(); @@ -18,8 +17,7 @@ void ins(string ne, int ix) { } u = aca[u].nxt[ch]; } - aca[u].leaf = 1; - aca[u].ix.push_back(ix); + aca[u].leaf = 1; aca[u].ix.push_back(ix); } int go(int u, int c); diff --git a/fontes/angular-sweep.h b/fontes/angular-sweep.h index b036af5ce10ae16cbdf2e1e1fcb4748ca0e73ddd..6ece937ae980dc96aaf50d440153a44dd4349399 100644 --- a/fontes/angular-sweep.h +++ b/fontes/angular-sweep.h @@ -7,14 +7,11 @@ int get_points_inside(int i, double r, int n) { ang.push_back(dbi(a - b, j)); ang.push_back(dbi(a + b, j)); } - - sort(begin(ang), end(ang)); - + sort(all(ang)); int count = 1, res = 1; for (auto angle : ang) { count += angle.second ? 1 : -1; res = max(res, count); } - return res; } diff --git a/fontes/bellman-ford.h b/fontes/bellman-ford.h index 7a95d6ecd05acb6aa40bfa66d79e5aa92e100aeb..07b0cb1af47a6fad8802faf678841ff40d909183 100644 --- a/fontes/bellman-ford.h +++ b/fontes/bellman-ford.h @@ -3,14 +3,14 @@ vector<edge> edges; vector<int> d (N, oo); int bellman_ford(int src, int dest, int n) { - d[src] = 0; - for (int i = 0; i < n - 1; i++) + d[src] = 0; + for (int i = 0; i < n - 1; i++) for (auto e : edges) - if (d[e.u] != oo && d[e.v] > d[e.u] + e.w) - d[e.v] = d[e.u] + e.w; - // Verificação de ciclos negativos - for (auto e : edges) - if (d[e.u] != oo && d[e.v] > d[e.u] + e.w) - return -oo; - return d[dest]; + if (d[e.u] != oo && d[e.v] > d[e.u] + e.w) + d[e.v] = d[e.u] + e.w; + // Verificação de ciclos negativos + for (auto e : edges) + if (d[e.u] != oo && d[e.v] > d[e.u] + e.w) + return -oo; + return d[dest]; } diff --git a/fontes/centroid.h b/fontes/centroid.h index 13c0482914e1b81ce8070589c695116f739357e4..837de3e71496ed6c317f641ce8550824c4b80170 100644 --- a/fontes/centroid.h +++ b/fontes/centroid.h @@ -8,8 +8,9 @@ int calc_size(int u, int p) { } int find_centroid(int u, int p, int n) { - for (int v : g[u]) if (v != p && !vis[v] && sz[v] > n/2) - return find_centroid(v, u, n); + for (int v : g[u]) + if (v != p && !vis[v] && sz[v] > n/2) + return find_centroid(v, u, n); return u; } diff --git a/fontes/coordinate-compression.h b/fontes/coordinate-compression.h index f4202db174d79a314d48049d072854c31c9814a4..cd5285a5f399f422609f2efefb223481bbe5ccca 100644 --- a/fontes/coordinate-compression.h +++ b/fontes/coordinate-compression.h @@ -1,5 +1,5 @@ void compress(vector<int>& v, vector<int>& cv) { - set<int> vs (begin(v), end(v)); + set<int> vs (all(v)); map<int, int> to, fm; int ix = 0; for (int i : vs) { to[i] = ix; fm[ix] = i; ix++; } diff --git a/fontes/custom-hash.h b/fontes/custom-hash.h index 7f4867067d473ddfafa047e2f1a3d0bb6e6bfd6d..e80c99aa5a203869bdbc0f649abb0bf1519d7742 100644 --- a/fontes/custom-hash.h +++ b/fontes/custom-hash.h @@ -9,7 +9,8 @@ struct custom_hash { size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = - chrono::steady_clock::now().time_since_epoch().count(); + chrono::steady_clock::now() + .time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } }; diff --git a/fontes/digit-dp.h b/fontes/digit-dp.h index 40ed98bef64c75ebc1aa843202f1e3c8b02fc4fa..e665c2c641af978bb572212e0f47d137bc9bbad1 100644 --- a/fontes/digit-dp.h +++ b/fontes/digit-dp.h @@ -13,6 +13,6 @@ ll digit_dp(int i, int l, bool lo, bool nz) { } ll solve(ll b) { - num = to_string(b); reverse(begin(num), end(num)); + num = to_string(b); reverse(all(num)); return digit_dp(num.size()-1, 10, 0, 0); } diff --git a/fontes/dijkstra.h b/fontes/dijkstra.h index efa8912a2945fd524ce123dd335e49b53d92c78e..2a757a9becd674585f06ee326e1b3370e2263587 100644 --- a/fontes/dijkstra.h +++ b/fontes/dijkstra.h @@ -2,8 +2,7 @@ void dijkstra(int src, int dest, int n) { vector<ll> d (n, oo); vector<bool> vis (n); vector<vector<int>> dag (n); priority_queue<ii, vector<ii>, greater<ii>> q; - d[src] = 0; - q.push({0, src}); + d[src] = 0; q.push({0, src}); while (!q.empty()) { auto [c, u] = q.top(); q.pop(); if (vis[u]) { continue; } diff --git a/fontes/dinic.h b/fontes/dinic.h index bc9a9ef45c44b6d52d31e503d1114f3398e2b0f3..00a90e7f52934b6bf6901202fa18789e6c5e946d 100644 --- a/fontes/dinic.h +++ b/fontes/dinic.h @@ -1,16 +1,7 @@ -struct edge { int u, v; ll cap, flow; }; -vector<edge> edges; -const ll oo = 1e18; vector<vector<int>> res (N); vector<int> level (N), ptr (N); -queue<int> q; - -void link(int u, int v, ll cap) { - res[u].push_back(edges.size()); - edges.push_back({ u, v, cap, 0 }); - res[v].push_back(edges.size()); - edges.push_back({ v, u, 0, 0 }); -} +struct edge { int u, v; ll cap, flow = 0; }; +vector<edge> edges; queue<int> q; bool minimum_path(int s, int t) { while (!q.empty()) { @@ -29,15 +20,13 @@ ll dfs(int u, int t, ll pushed) { if (pushed == 0) { return 0; } if (u == t) { return pushed; } for (int& cid = ptr[u]; cid < res[u].size(); cid++) { - int i = res[u][cid]; - int v = edges[i].v; + int i = res[u][cid], v = edges[i].v; if (level[u] + 1 != level[v]) { continue; } if (edges[i].cap - edges[i].flow < 1) { continue; } ll tr = dfs(v, t, min(pushed, edges[i].cap - edges[i].flow)); if (tr == 0) { continue; } - edges[i].flow += tr; - edges[i^1].flow -= tr; + edges[i].flow += tr; edges[i^1].flow -= tr; return tr; } return 0; @@ -46,11 +35,11 @@ ll dfs(int u, int t, ll pushed) { ll dinic /* O(EV^2) */(int s, int t) { ll max_flow = 0; while (1) { - fill(begin(level), end(level), -1); + fill(all(level), -1); level[s] = 0; q.push(s); if (!minimum_path(s, t)) { break; } - fill(begin(ptr), end(ptr), 0); - while (ll pushed = dfs(s, t, oo)) + fill(all(ptr), 0); + while (ll pushed = dfs(s, t, 1e18)) max_flow += pushed; } return max_flow; diff --git a/fontes/division-trick.h b/fontes/division-trick.h index 0c64e3786d9ddc3f8625e32393fe2a26b11be30d..404099acfa83b3fe425686022204c0d741e6f6c6 100644 --- a/fontes/division-trick.h +++ b/fontes/division-trick.h @@ -1,4 +1,4 @@ -for (int l = 1, r; l <= n; l = r + 1) { - r = n / ( n / l ) ; - // n / i has the same value for l <= i <= r +for (int l = 1, r; l <= n; l = r+1) { + r = n/(n/l); + // n/i has the same value for l <= i <= r } diff --git a/fontes/eulerian-path.h b/fontes/eulerian-path.h index f46d20798961df8dbdd7c39f8da13e4fe2126d77..9bb3a344d634e450cec9d8c9d565928004d042ca 100644 --- a/fontes/eulerian-path.h +++ b/fontes/eulerian-path.h @@ -15,7 +15,8 @@ vector<int> eulerian_path(int src, int n) { st.push(v); } } - for (int u = 0; u < n; u++) if (g[u].size()) { return {}; } - reverse(begin(res), end(res)); + for (int u = 0; u < n; u++) if (g[u].size()) + return {}; + reverse(all(res)); return res; } diff --git a/fontes/ford-fulkerson-edmons-karp-min-cost.h b/fontes/ford-fulkerson-edmons-karp-min-cost.h index 8430eadad4399a09546dd4b56a4112bd878a5655..97f25d37f22c1e68ebc56b599bc2844b3e204219 100644 --- a/fontes/ford-fulkerson-edmons-karp-min-cost.h +++ b/fontes/ford-fulkerson-edmons-karp-min-cost.h @@ -11,7 +11,7 @@ void link(int u, int v, int cap, int cost) { } bool minimum_path(int s, int t) { - fill(begin(dist), end(dist), oo); + fill(all(dist), oo); queue<int> q; q.push(s); dist[s] = 0; while (!q.empty()) { int u = q.front(); q.pop(); diff --git a/fontes/ford-fulkerson-edmons-karp.h b/fontes/ford-fulkerson-edmons-karp.h index 23a22d7c0717bf732eb673724ad2e3969adeaf1b..5def2dedfa683c4709bcc1d5fdd8c2e084f8c448 100644 --- a/fontes/ford-fulkerson-edmons-karp.h +++ b/fontes/ford-fulkerson-edmons-karp.h @@ -9,7 +9,7 @@ void link(int u, int v, int c) { } bool minimum_path(int s, int t) { - fill(begin(dist), end(dist), oo); + fill(all(dist), oo); queue<int> q; q.push(s); dist[s] = 0; while (!q.empty()) { int u = q.front(); q.pop(); diff --git a/fontes/graham.h b/fontes/graham.h index b204e5c7602481f1fb1ccc9640237d5a30fdc268..ddf2c92e3fa1b50ecb1b3fe85581a51da0b7a0e2 100644 --- a/fontes/graham.h +++ b/fontes/graham.h @@ -1,10 +1,10 @@ vector<pt> convex_hull(vector<pt>& ps, bool col = 0) { - pt p0 = *min_element(begin(ps), end(ps), [](pt a, pt b) { + pt p0 = *min_element(all(ps), [](pt a, pt b) { return make_pair(a.py, a.px) < make_pair(b.py, b.px); }); - sort(begin(ps), end(ps), [&p0](pt a, pt b) { + sort(all(ps), [&p0](pt a, pt b) { int o = seg_ornt(p0, a, b); - return o < 0 || (o == 0 && norm(p0 - a) < norm(p0 - b)); + return o < 0 || (o == 0 && norm(p0-a) < norm(p0-b)); }); if (col) { int i = ps.size(); i--; diff --git a/fontes/hld-kth.h b/fontes/hld-kth.h index c3814bbd56d35269ae25532f744a539ffcfede90..933af43a5ccb0a21668f481e2ef9053df9709037 100644 --- a/fontes/hld-kth.h +++ b/fontes/hld-kth.h @@ -11,7 +11,8 @@ int hld_len(int u, int v) { int hld_kth(int u, int v, int k) { bool sw = 0; int l = 0, r = hld_len(u, v)-1; for (; hds[u] != hds[v]; v = par[hds[v]]) { - if (dep[hds[u]] > dep[hds[v]]) { swap(u, v); sw ^= 1; } + if (dep[hds[u]] > dep[hds[v]]) + { swap(u, v); sw ^= 1; } int sz = ixs[v]-ixs[hds[v]]+1; int i = sw ? k-l : r-k; if (0 <= i && i < sz) { return rixs[ixs[v]-i]; } @@ -26,7 +27,8 @@ vector<int> hld_path(int u, int v, int k) { int len = hld_len(u, v); vector<int> path (len); bool sw = 0; int l = 0, r = len-1; for (; hds[u] != hds[v]; v = par[hds[v]]) { - if (dep[hds[u]] > dep[hds[v]]) { swap(u, v); sw ^= 1; } + if (dep[hds[u]] > dep[hds[v]]) + { swap(u, v); sw ^= 1; } for (int i = ixs[v]; i >= ixs[hds[v]]; i--) { path[sw ? l++ : r--] = rixs[i]; } diff --git a/fontes/inclusion-exclusion.h b/fontes/inclusion-exclusion.h index 8bc6d03867e29f4c6b5640c24f37280e590f095d..cb0e4470651fdcf52ec85733d59d2f43a7f61e4f 100644 --- a/fontes/inclusion-exclusion.h +++ b/fontes/inclusion-exclusion.h @@ -1,18 +1,15 @@ ll inclusion_exclusion(int n, int m, ll a, ll d) { vector<ll> exc { a, a+d, a+2*d, a+3*d, a+4*d }; - ll total = 0; for (int b = 1; b < (1<<5); b++) { ll x = 1; for (int i = 0; i < 5; i++) if (b & (1<<i)) { if (x > ceil_div(m, exc[i]) * gcd(x, exc[i])) { - x = b+1; break; - } + x = b+1; break; } x = lcm(x, exc[i]); } ll s = (__builtin_popcount(b) % 2) ? +1 : -1; total += s * multiples_inclusive(n, m, x); } - cout << (m-n+1) - total << "\n"; } diff --git a/fontes/kd-tree.h b/fontes/kd-tree.h index ec3db72753c54e45ed78a1336cdcf252552ee158..81b44b042d4d04a81ebeb311a6076dca4f659b2a 100644 --- a/fontes/kd-tree.h +++ b/fontes/kd-tree.h @@ -5,20 +5,18 @@ int get_ii(pt pair, int ix) { struct kdtree { struct node { - node(pt& p) : p(p), left(nullptr), right(nullptr) {} + node(pt& p) : p(p), left(0), right(0) {} double dist_sq(const pt& o) { return norm(o - p); } pt p; node* left, *right; }; node* root = 0; - vector<double> best; - vector<node> t; + vector<double> best; vector<node> t; struct cmp { - cmp(size_t _index) : ix(_index) {} + size_t ix; cmp(size_t _index) : ix(_index) {} bool operator()(const node& n1, const node& n2) { return get_ii(n1.p, ix) < get_ii(n2.p, ix); } - size_t ix; }; node* make_tree(size_t begin, size_t end, size_t ix) { @@ -32,12 +30,10 @@ struct kdtree { } void nearest_k(node* r, const pt& p, size_t ix, int k) { - if (r == nullptr) - return; + if (r == nullptr) { return; } double d = r->dist_sq(p); if (best.size() < k || d < best.back()) { - best.push_back(d); - sort(begin(best), end(best)); + best.push_back(d); sort(all(best)); if (best.size() > k) best.erase(begin(best)+k, end(best)); } @@ -56,12 +52,10 @@ struct kdtree { double nearest_k(const pt& p, int k) { if (root == 0) { throw logic_error("empty tree"); } - best.clear(); - nearest_k(root, p, 0, k); + best.clear(); nearest_k(root, p, 0, k); double acc = 0; - for (int i = 0; i < best.size(); i++) { + for (int i = 0; i < best.size(); i++) acc += sqrt(best[i]); - } return acc; } }; diff --git a/fontes/kmp-automaton.h b/fontes/kmp-automaton.h index c07a6c82e53427c54f68536b435a13db9de5a935..77720266c39a7aded7b512284b6f48a22935a42b 100644 --- a/fontes/kmp-automaton.h +++ b/fontes/kmp-automaton.h @@ -1,16 +1,14 @@ -void compute_automaton(string s, vector<vector<int>>& aut) { - s += '#'; - int n = s.size(); +vector<vector<int>> kmp_automaton(string s) { + s += '#'; int n = s.size(); vector<int> pi = pre(s); - aut.assign(n, vector<int>(26)); - for (int i = 0; i < n; i++) { + vector<vector<int>> aut (n, vector<int>(26)); + for (int i = 0; i < n; i++) for (int c = 0; c < 26; c++) { int j = i; while (j > 0 && 'a' + c != s[j]) j = pi[j-1]; - if ('a' + c == s[j]) - j++; + if ('a' + c == s[j]) { j++; } aut[i][c] = j; } - } + return aut; } diff --git a/fontes/kruskal.h b/fontes/kruskal.h index 7d0c55ba91297f88a498203a5d296b7352ce59cd..08633801142cad3f6105fda66c20b29d695231cc 100644 --- a/fontes/kruskal.h +++ b/fontes/kruskal.h @@ -4,10 +4,8 @@ struct edge { }; int kruskal(int n) { - sort(begin(edges), end(edges)); - ds_init(n); - int components = n; - ll sum = 0; + sort(all(edges)); + ds_init(n); int components = n; ll sum = 0; for (auto [u, v, w] : edges) { if (components == 1) { break; } if (ds_find(u) != ds_find(v)) { diff --git a/fontes/kuhn.h b/fontes/kuhn.h index f5fee6fb6d8355659b9401ef0192e9e95011aaab..855e504ebb8f30b46d38ccc965db4161161edaac 100644 --- a/fontes/kuhn.h +++ b/fontes/kuhn.h @@ -2,8 +2,7 @@ vector<vector<int>> g (L); vector<int> matchr (R, -1); int dfs(int u) { - if (vis[u] == cts) { return 0; } - vis[u] = cts; + if (vis[u] == cts) { return 0; } vis[u] = cts; for (int v : g[u]) if (matchr[v] == -1 || dfs(matchr[v])) { matchr[v] = u; return 1; diff --git a/fontes/lazy-segment-tree.h b/fontes/lazy-segment-tree.h index 3c66786719a0acd25d9ddd4068b8d16e46c4bfb8..7969c44ecb3741babd0b7e96483896b1ab6c088f 100644 --- a/fontes/lazy-segment-tree.h +++ b/fontes/lazy-segment-tree.h @@ -40,8 +40,7 @@ void push(int i) { void apply_inclusive(int l, int r, int n, char op = '\0', ll x = 0) { - r++; - dlta d; + r++; dlta d; if (op == '+') { d.add = x; } if (op == '=') { d.set = x; } int tl = l += n, tr = r += n, sz = 1; diff --git a/fontes/lca-offline.h b/fontes/lca-offline.h index 5f00b8e5fbe904e19150e982e01a9c17404de8fe..8a87143ff8eff866426dc399316d9973ccb373da 100644 --- a/fontes/lca-offline.h +++ b/fontes/lca-offline.h @@ -4,9 +4,7 @@ vector<int> anc (N); vector<bool> vis (N); void dfs(int u) { vis[u] = 1; anc[u] = u; for (int v : adj[u]) if (!vis[v]) { - dfs(v); - ds_unite(u, v); - anc[ds_find(u)] = u; + 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/lca-square-root-decomposition.h b/fontes/lca-square-root-decomposition.h index 41da9b4733c3612433535b3f284b0acc0476d7fb..1de4fddaa1b82fc6dd889d403217fe74d27e6fa0 100644 --- a/fontes/lca-square-root-decomposition.h +++ b/fontes/lca-square-root-decomposition.h @@ -1,8 +1,8 @@ int std_lca(int a, int b) { - if (!(depth[a]/B > depth[b]/B)) { swap(a, b); } - while (depth[a]/B > depth[b]/B) { a = bup[a]; } - if (!(depth[a] > depth[b])) { swap(a, b); } - while (depth[a] > depth[b]) { a = up[a]; } - while (a != b) { a = up[a]; b = up[b]; } - return a; + if (!(depth[a]/B > depth[b]/B)) { swap(a, b); } + while (depth[a]/B > depth[b]/B) { a = bup[a]; } + if (!(depth[a] > depth[b])) { swap(a, b); } + while (depth[a] > depth[b]) { a = up[a]; } + while (a != b) { a = up[a]; b = up[b]; } + return a; } diff --git a/fontes/longest-increasing-subsequence-n-lg-n.h b/fontes/longest-increasing-subsequence-n-lg-n.h index f7c6375d71d9a444c1b56da70d29faf34f4c91f0..474ab51b6b712f989788ccca5b9d2ed9ade51901 100644 --- a/fontes/longest-increasing-subsequence-n-lg-n.h +++ b/fontes/longest-increasing-subsequence-n-lg-n.h @@ -5,8 +5,7 @@ int lis(vector<int>& v) { for (int i = 1; i < n; i++) if (v[i] > ans.back()) { ans.push_back(v[i]); } else { - ans[lower_bound(begin(ans), end(ans), v[i]) - - begin(ans)] = v[i]; + ans[lower_bound(all(ans), v[i]) - begin(ans)] = v[i]; } return ans.size(); } diff --git a/fontes/merge-sort.h b/fontes/merge-sort.h index fedf3dcc4c733f361876dfe2410d8fc4045aad4f..3dc37f62bb92e8200c4b367c1ee4323defb9f520 100644 --- a/fontes/merge-sort.h +++ b/fontes/merge-sort.h @@ -13,5 +13,5 @@ void merge_sort(int l, int r) { } else if (i < mi) { aux[k] = a[i++]; } else { aux[k] = a[j++]; } } - copy(begin(aux), end(aux), begin(a)+l); + copy(all(aux), begin(a)+l); } diff --git a/fontes/min-queue-2.h b/fontes/min-queue-2.h deleted file mode 100644 index 7e95f6b41a179c990d6cae53bd0b553cc3251138..0000000000000000000000000000000000000000 --- a/fontes/min-queue-2.h +++ /dev/null @@ -1,13 +0,0 @@ -deque<pair<int, int>> q; -int add = 0, rem = 0; -void enqueue_el(int x) { - while (!q.empty() && q.back().first > x) - q.pop_back(); - q.push_back({ x, add++ }); -} -void dequeue_el() { - if (!q.empty() && q.front().second == rem) - q.pop_front(); - rem++; -} -int min_el() { return q.front().first; } diff --git a/fontes/min-queue-3.h b/fontes/min-queue-3.h deleted file mode 100644 index 1c0fd81e5c21023657cca97939dca3d5087c4f2a..0000000000000000000000000000000000000000 --- a/fontes/min-queue-3.h +++ /dev/null @@ -1,19 +0,0 @@ -stack<pair<int, int>> s1, s2; - -void enqueue_el(int x) { - int m = min(x, s1.size() ? s1.top().second : oo); - s1.push({ x, m }); -} -int dequeue_el() { - if (s2.empty()) while (!s1.empty()) { - int el = s1.top().first; s1.pop(); - int m = min(el, s2.size() ? s2.top().second : oo); - s2.push({ el, m }); - } - int r = s2.top().first; s2.pop(); return r; -} -int min_el() { - return min( - s1.size() ? s1.top().second : oo, - s2.size() ? s2.top().second : oo); -} diff --git a/fontes/min-queue.h b/fontes/min-queue.h index 913599310ca63e8bcd7841cefd4929d539f7d15a..1c0fd81e5c21023657cca97939dca3d5087c4f2a 100644 --- a/fontes/min-queue.h +++ b/fontes/min-queue.h @@ -1,11 +1,19 @@ -deque<int> q; +stack<pair<int, int>> s1, s2; + void enqueue_el(int x) { - while (!q.empty() && q.back() > x) - q.pop_back(); - q.push_back(x); + int m = min(x, s1.size() ? s1.top().second : oo); + s1.push({ x, m }); } -void dequeue_el(int x) { - if (!q.empty() && q.front() == x) - q.pop_front(); +int dequeue_el() { + if (s2.empty()) while (!s1.empty()) { + int el = s1.top().first; s1.pop(); + int m = min(el, s2.size() ? s2.top().second : oo); + s2.push({ el, m }); + } + int r = s2.top().first; s2.pop(); return r; +} +int min_el() { + return min( + s1.size() ? s1.top().second : oo, + s2.size() ? s2.top().second : oo); } -int min_el() { return q.front(); } diff --git a/fontes/mo-algorithm.h b/fontes/mo-algorithm.h index b49ee49026d7faea6a8df0b8136cec1f7a200741..ac6bad96d094a6b5958935541864f6208c32537b 100644 --- a/fontes/mo-algorithm.h +++ b/fontes/mo-algorithm.h @@ -1,6 +1,6 @@ vector<int> mo(vector<qry> qs) { vector<int> ans (qs.size()); - sort(begin(qs), end(qs), [](qry a, qry b) { + sort(all(qs), [](qry a, qry b) { if (a.l/B != b.l/B) { return a.l < b.l; } return ((a.l/B) % 2 == 0) ^ (a.r < b.r); }); diff --git a/fontes/modular-integer.h b/fontes/modular-integer.h index a6276a837526d2d6d099a8eaa8dfbfe4016ea6dd..34782a40abccec51a987a4b9d0890bcc734ea0ed 100644 --- a/fontes/modular-integer.h +++ b/fontes/modular-integer.h @@ -1,10 +1,8 @@ template<int p> struct modint { - int x; - modint() : x(0) {} + int x; modint() : x(0) {} modint(ll a) : x(a) { if (!(-p < x && x < p)) x %= p; - if (x < 0) x += p; - } + if (x < 0) x += p; } using m = modint; #define DEF(n, b) m& n(const m& a) { b; return *this; } DEF(operator+=, { x += a.x; if (x >= p) { x -= p; } }) diff --git a/fontes/monotone.h b/fontes/monotone.h index e73b3f0a20a961f974e50f28e0020d959edb8351..a4c29668a229f72fb2333da227d4d5c1c5c2b3e1 100644 --- a/fontes/monotone.h +++ b/fontes/monotone.h @@ -1,6 +1,6 @@ vector<pt> convex_hull(vector<pt>& ps, bool col = 0) { int k = 0, n = ps.size(); vector<pt> ans (2*n); - sort(begin(ps), end(ps), [](pt a, pt b) { + sort(all(ps), [](pt a, pt b) { return make_pair(a.px, a.py) < make_pair(b.px, b.py); }); for (int i = 0; i < n; i++) { diff --git a/fontes/next-combination.h b/fontes/next-combination.h index 1665b46aa438ffeb00325f1fed3a10ed762da900..57df9b6034dec79ecd48abbe1e9ee9ab31bdd7d3 100644 --- a/fontes/next-combination.h +++ b/fontes/next-combination.h @@ -2,7 +2,7 @@ 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) { a[i]++; - for (int j = i + 1; j < k; j++) + for (int j = i+1; j < k; j++) a[j] = a[j-1] + 1; return 1; } diff --git a/fontes/next-greater-element.h b/fontes/next-greater-element.h index f61e2aeb7a675927f278cf6a49681d8e4525c8f4..da7a813ebbf719be6fa2e91c60c4b0e61ead813a 100644 --- a/fontes/next-greater-element.h +++ b/fontes/next-greater-element.h @@ -1,5 +1,7 @@ stack<int> nge; +// start from the end for previous for (int i = 0; i < n; i++) { + // < is greater next, > is lesser next while (!nge.empty() && v[nge.top()] < v[i]) { ans[nge.top()] = i; nge.pop(); } diff --git a/fontes/next-lesser-element.h b/fontes/next-lesser-element.h deleted file mode 100644 index a2c886358e341a85fd71ac267f25768a415ff214..0000000000000000000000000000000000000000 --- a/fontes/next-lesser-element.h +++ /dev/null @@ -1,7 +0,0 @@ -stack<int> nle; -for (int i = 0; i < n; i++) { - while (!nle.empty() && v[nle.top()] > v[i]) { - ans[nle.top()] = i; nle.pop(); - } - nle.push(i); -} diff --git a/fontes/optimal-schedule-jobs.h b/fontes/optimal-schedule-jobs.h index b8165b18ee841fe18f6574b0a83694dbe59507f1..25c49eefc1320dae2992a9807bea2480a60f805a 100644 --- a/fontes/optimal-schedule-jobs.h +++ b/fontes/optimal-schedule-jobs.h @@ -4,7 +4,7 @@ struct job { }; vector<int> compute_schedule(vector<job> jobs) { - sort(begin(jobs), end(jobs)); + sort(all(jobs)); set<pair<int,int>> s; vector<int> schedule; for (int i = jobs.size()-1; i >= 0; i--) { int t = jobs[i].dl - (i ? jobs[i-1].dl : 0); diff --git a/fontes/previous-greater-element.h b/fontes/previous-greater-element.h deleted file mode 100644 index b9d1e97f2c324f5eb897d06764a64b9af98451e3..0000000000000000000000000000000000000000 --- a/fontes/previous-greater-element.h +++ /dev/null @@ -1,7 +0,0 @@ -stack<int> pge; -for (int i = n-1; i >= 0; i--) { - while (!pge.empty() && v[pge.top()] < v[i]) { - ans[pge.top()] = i; pge.pop(); - } - pge.push(i); -} diff --git a/fontes/previous-lesser-element.h b/fontes/previous-lesser-element.h deleted file mode 100644 index 97985c2655f621495a5441cfcdf02d093089a9c8..0000000000000000000000000000000000000000 --- a/fontes/previous-lesser-element.h +++ /dev/null @@ -1,7 +0,0 @@ -stack<int> ple; -for (int i = n-1; i >= 0; i--) { - while (!ple.empty() && v[ple.top()] > v[i]) { - ans[ple.top()] = i; ple.pop(); - } - ple.push(i); -} diff --git a/fontes/prim.h b/fontes/prim.h index 806f81e1cd54853ac77490625039acd74e2973a6..33dadb076a2836cf68746c914fcb835bb1a6acbe 100644 --- a/fontes/prim.h +++ b/fontes/prim.h @@ -1,14 +1,11 @@ -vector<bool> vis (N); -vector<int> par (N, -1); -vector<ll> d (N, oo); -vector<vector<ii>> pt (N); - -ll prim(int src) { +ll prim(int src, int n) { + vector<bool> vis (n); vector<int> par (n, -1); + vector<ll> d (n, oo); vector<vector<ii>> pt (n); ll sum = 0; - priority_queue<ii, vector<ii>, greater<ii>> Q; - Q.push(ii(d[src] = 0, src)); - while (!Q.empty()) { - auto [c, u] = Q.top(); Q.pop(); + priority_queue<ii, vector<ii>, greater<ii>> q; + q.push(ii(d[src] = 0, src)); + while (!q.empty()) { + auto [c, u] = q.top(); q.pop(); if (vis[u]) { continue; } vis[u] = 1; if (par[u] != -1) { @@ -19,7 +16,7 @@ ll prim(int src) { sum += c; for (auto [v, w] : g[u]) if (!vis[v] && w < d[v]) { - Q.push(ii(d[v] = w, v)); + q.push(ii(d[v] = w, v)); par[v] = u; } } diff --git a/fontes/rectangle-intersection.h b/fontes/rectangle-intersection.h index 6f2f88f605c142a36119f039e7313b62675c4655..91d0e0b1768f2a83d76a3f43b792437be8c034bf 100644 --- a/fontes/rectangle-intersection.h +++ b/fontes/rectangle-intersection.h @@ -1,5 +1,6 @@ bool has_intersection(pt tl0, pt br0, pt tl1, pt br1) { pt tl = pt(max(tl0.px, tl1.px), max(tl0.py, tl1.py)); pt br = pt(min(br0.px, br1.px), min(br0.py, br1.py)); - return make_pair(tl.px, tl.py) <= make_pair(br.px, br.py); + return make_pair(tl.px, tl.py) + <= make_pair(br.px, br.py); } diff --git a/fontes/recursive-lazy-segment-tree.h b/fontes/recursive-lazy-segment-tree.h index a586194ceea378aa615ef178357109a165a20d29..dd638c60142a41ad77cfdb485cb46cd96c385031 100644 --- a/fontes/recursive-lazy-segment-tree.h +++ b/fontes/recursive-lazy-segment-tree.h @@ -27,27 +27,21 @@ void push(int ti, int tl, int tm, int tr) { lazy[ti] = 0; } -void set_inclusive(int l, int r, int d, - int ti=1, int tl=1, int tr=N) { - if (l > r) { return; } - if (l == tl && tr == r) { - t[ti] = ll(d) * FACTOR(tr - tl + 1); - sety[ti] = d; lazy[ti] = 0; return; } - int tm = (tl + tr) / 2; push(ti, tl, tm, tr); - set_inclusive(l, min(r, tm), d, ti*2, tl, tm); - set_inclusive(max(l, tm+1), r, d, ti*2+1, tm+1, tr); - t[ti] = OP(t[ti*2], t[ti*2+1]); -} - -void add_inclusive(int l, int r, int d, +void update_inclusive(int l, int r, char op, int d, int ti=1, int tl=1, int tr=N) { if (l > r) { return; } if (l == tl && tr == r) { + if (op == '=') { + t[ti] = 0; sety[ti] = d; lazy[ti] = 0; + } else if (op == '+') { + lazy[ti] += d; + } t[ti] += ll(d) * FACTOR(tr - tl + 1); - lazy[ti] += d; return; } + return; + } int tm = (tl + tr) / 2; push(ti, tl, tm, tr); - add_inclusive(l, min(r, tm), d, ti*2, tl, tm); - add_inclusive(max(l, tm+1), r, d, ti*2+1, tm+1, tr); + update_inclusive(l, min(r, tm), d, ti*2, tl, tm); + update_inclusive(max(l, tm+1), r, d, ti*2+1, tm+1, tr); t[ti] = OP(t[ti*2], t[ti*2+1]); } diff --git a/fontes/spfa.h b/fontes/spfa.h index de88162aada997887b0c8dc5e8c20539af64c2b2..661c124255953598361e3501dc067da7963cb2b8 100644 --- a/fontes/spfa.h +++ b/fontes/spfa.h @@ -1,9 +1,7 @@ bool spfa(int src, int n) { - vector<int> cnt (n); - vector<bool> queu (n); + vector<int> cnt (n); vector<bool> queu (n); vector<ll> d (n, oo); - d[src] = 0; - queue<int> q; q.push(src); + queue<int> q; q.push(src); d[src] = 0; while (!q.empty()) { int u = q.front(); q.pop(); queu[u] = 0; diff --git a/fontes/stable-matching.h b/fontes/stable-matching.h index e7817b438784cf34236176d1e9ccce1cf75bd5b9..ff39bf1a9f7a0d42eb2dc44dde7eb025052ac2c2 100644 --- a/fontes/stable-matching.h +++ b/fontes/stable-matching.h @@ -1,13 +1,11 @@ vector<vi> pm (N, vi(N)); // [m][j] = w vector<vi> pwix (N, vi(N+1)); // [w][m] = j - vector<bool> single (N, 1); vector<int> match (N, -1), watch (N, N); vector<ii> galeshapley(int n) { // sentinel for (int w = 0; w < n; w++) { pwix[w][n] = n; } - bool done = 0; while (!done) { done = 1; @@ -20,7 +18,6 @@ vector<ii> galeshapley(int n) { } } } - vector<ii> ans; for (int m = 0; m < n; m++) ans.push_back(ii(m, pm[m][match[m]])); diff --git a/fontes/stoer-wagner.h b/fontes/stoer-wagner.h index f03b4fe16a09f309a16444b0ab5df97019173846..65a50eecc31e79813896ba4d3788a58900e6b501 100644 --- a/fontes/stoer-wagner.h +++ b/fontes/stoer-wagner.h @@ -2,9 +2,7 @@ vector<vector<int>> res (N, vector<int>(N)); vector<bool> bin (N); int contract(int n, int &s, int &t) { - vector<int> dist (n); - vector<bool> vis (n); - + vector<int> dist (n); vector<bool> vis (n); int mincut, maxc; for (int i = 0; i < n; i++) { int k = -1; maxc = -1; @@ -13,7 +11,7 @@ int contract(int n, int &s, int &t) { k = j; maxc = dist[j]; } - if (k == -1) return mincut; + if (k == -1) { return mincut; } s = t; t = k; mincut = maxc; vis[k] = 1; for (int j = 1; j < n; j++) @@ -25,8 +23,7 @@ int contract(int n, int &s, int &t) { } int stoer_wagner(int n) { - int mincut = oo; - int s, t; + int mincut = oo, s, t; for (int i = 0; i < n-1; i++) { mincut = min(mincut, contract(n, s, t)); if (mincut == 0) { return 0; } diff --git a/fontes/suffix-array-radix.h b/fontes/suffix-array-radix.h index 89bc425edd56c8c858653fb89bfc006947619c5c..0837d4f35d9e1af2e60066e759f9fd6640d3c652 100644 --- a/fontes/suffix-array-radix.h +++ b/fontes/suffix-array-radix.h @@ -2,7 +2,7 @@ pair<vector<int>, vector<int>> build_sa(string s, int n) { vector<int> sk (n), sa (n); vector<pair<int, int>> a (n); for (int i = 0; i < n; i++) { a[i] = { s[i], i }; } - sort(begin(a), end(a)); + sort(all(a)); for (int i = 0; i < n; i++) { tie(sk[i], sa[i]) = a[i]; } vector<int> nsk(n); for (int i = 1, r = 0; i < n; i++) diff --git a/fontes/suffix-array.h b/fontes/suffix-array.h index e66e8530eb5541fb2f177b8561273161ad7eecdd..5b29aae60acade5118ac692023d7d73c91a2a1ec 100644 --- a/fontes/suffix-array.h +++ b/fontes/suffix-array.h @@ -3,7 +3,7 @@ pair<vector<int>, vector<int>> build_sa(string s) { int n = s.size(); - vector<int> sk (begin(s), end(s)); + vector<int> sk (all(s)); vector<pair<pair<int, int>, int>> a(n); for (int k = 1; k < n; k *= 2) { for (int i = 0; i < n; i++) @@ -18,7 +18,7 @@ pair<vector<int>, vector<int>> build_sa(string s) { return make_pair(sa, sk); } -vector<int> compute_lcp (vector<int> sa, vector<int> sk) { +vector<int> make_lcp(vector<int> sa, vector<int> sk) { vector<int> lcp (n); int k = 0; for (int i = 0; i < n-1; i++) { diff --git a/fontes/suffix-automaton.h b/fontes/suffix-automaton.h index ec7e60b61948a802ff6c598c2ce05c344849f565..edbee152f1ce35fd4fbf09bff8bea58153b3c0a5 100644 --- a/fontes/suffix-automaton.h +++ b/fontes/suffix-automaton.h @@ -1,6 +1,7 @@ int last = 0, sz = 1; vector<int> len (2*N), lnk (2*N), acc (2*N); vector<vector<int>> nxt (2*N, vector<int>(S)); + void add(int c) { int cur = sz++; len[cur] = len[last]+1; int p = last; last = cur; @@ -10,7 +11,7 @@ void add(int c) { int q = nxt[p][c]; if (len[q] == len[p]+1) { lnk[cur] = q; return; } int qq = sz++; len[qq] = len[p]+1; lnk[qq] = lnk[q]; - copy(begin(nxt[q]), end(nxt[q]), begin(nxt[qq])); + copy(all(nxt[q]), begin(nxt[qq])); for (; ~p && nxt[p][c] == q; p = lnk[p]) nxt[p][c] = qq; lnk[cur] = lnk[q] = qq; @@ -27,8 +28,7 @@ vector<int> ord; void reverse_topo(int u) { cnt[u] = 1; for (int c = 0; c < S; c++) if (nxt[u][c]) - if (!cnt[nxt[u][c]]) - reverse_topo(nxt[u][c]); + if (!cnt[nxt[u][c]]) { reverse_topo(nxt[u][c]); } ord.push_back(u); } void process_count() { @@ -45,8 +45,7 @@ int longest_common_substring(string& t) { for (int i = 0; i < t.size(); i++) { int c = t[i]; while (u && !nxt[u][c]) { - u = lnk[u]; l = len[u]; - } + u = lnk[u]; l = len[u]; } if (nxt[u][c]) { u = nxt[u][c]; l++; } else { u = 0; l = 0; } if (l > ans) { ans = l; pos = i; } @@ -56,7 +55,7 @@ int longest_common_substring(string& t) { int search(string& t) { int u = 0; for (auto c : t) { - u = nxt[u][to_i(c)]; - if (!u) { return 0; }} + u = nxt[u][to_i(c)]; if (!u) { return 0; } + } return cnt[u]; } diff --git a/fontes/template.cpp b/fontes/template.cpp index 151052969f9fde75a239a59eabec1e5095dddd9e..26a7db268f9b15e0d3a8460830b6f0947981da83 100644 --- a/fontes/template.cpp +++ b/fontes/template.cpp @@ -1,9 +1,6 @@ #include <bits/stdc++.h> using namespace std; using ll = long long; - -#define $(X) {if (DEBUG) { \ - cerr << __LINE__ << ":"; {x} cerr << endl;}} -#define _(X) {cerr << #X << " = " << X << " ";} +#define all(X) begin(X), end(X) int main() { cin.tie(0)->sync_with_stdio(0); diff --git a/fontes/topological-order.h b/fontes/topological-order.h index 10886bddb957f8f8f59e77e3d7ffd6f3a5515c9d..dbf4edb3b648d8c9a6ef00fab13ec5316738c283 100644 --- a/fontes/topological-order.h +++ b/fontes/topological-order.h @@ -8,7 +8,7 @@ void dfs_topo(int u) { } vector<int> toposort(int n) { - fill(begin(vis), begin(vis) + n, 0); + fill(begin(vis), begin(vis)+n, 0); vector<int> topo; for (int u = 0; u < n; u++) { dfs_topo(u); } while (!st.empty()) { diff --git a/fontes/trie.h b/fontes/trie.h deleted file mode 100644 index 113b9d9a7a20a86cd5dcd9cfd22869a4bc0608cf..0000000000000000000000000000000000000000 --- a/fontes/trie.h +++ /dev/null @@ -1,18 +0,0 @@ -struct trie { - vector<int> nxt; int cnt; bool leaf; - trie() : nxt (S, -1), cnt (0), leaf (0) {} -}; -vector<trie> t (1); -void ins(string ne) { - int u = 0; - for (char c : ne) { - int ch = to_i(c); - if (t[u].nxt[ch] == -1) { - t[u].nxt[ch] = t.size(); - trie n; t.push_back(n); - } - u = t[u].nxt[ch]; - t[u].cnt++; - } - t[u].leaf = 1; -} diff --git a/fontes/voronoi.h b/fontes/voronoi.h new file mode 100644 index 0000000000000000000000000000000000000000..580a713211b69276214871a0a4a72f5b9d568063 --- /dev/null +++ b/fontes/voronoi.h @@ -0,0 +1,215 @@ +using ii = pair<int, int>; using ld = long double; +const ld EPS = 1e-9; + +pt rot(pt a) { return pt(-a.py, a.px); } +ld sq(ld x) { return x*x; } + +// precondition is that they aren't collinear +pt point_in_line_line(seg a, seg b) { + return a.aa + vec(a) * (cross(vec(a.aa, b.aa), vec(b)) + / cross(vec(a), vec(b))); +} +pt line_intersect(pt a, pt b, pt u, pt v) { + return point_in_line_line(seg(u, u + v), + seg(a, a + b)); +} + +// precondition is that abc is a non-degenerate triangle +pt circumcenter(pt a, pt b, pt c) { + b = (a + b) * ld(.5); + c = (a + c) * ld(.5); + return point_in_line_line( + seg(b, b + rot(vec(a, b))), seg(c, c + rot(vec(a, c)))); +} + +ld parab_intersect(pt l, pt r, ld sw) { + if (abs(l.py - r.py) < abs(l.px - r.px) * EPS) { + int sign = l.px < r.px ? 1 : -1; + pt m = 0.5l * (l+r); + pt v = line_intersect(m, rot(r-l), pt(0, sw), pt(1, 0)); + pt w = line_intersect(m, rot(l-v), v, l-v); + ld l1 = abs(v-w); + ld l2 = sqrt(sq(sw-m.py) - norm(m-w)); + ld l3 = abs(l-v); + return v.px + (m.px - v.px) * l3 / (l1 + sign * l2); + } + int sign = l.py < r.py ? -1 : 1; + pt v = line_intersect(l, r-l, pt(0, sw), pt(1, 0)); + ld d1 = norm(0.5l * (l+r) - v); + ld d2 = norm(0.5l * (l-r)); + return v.px + sign * sqrt(max(0.0l, d1 - d2)); +} + +struct beach { + struct arc { + arc() {} + arc(pt p, int ix) : p(p), ix(ix), end(0), + link{0, 0}, par(0), prv(0), nxt(0) {} + pt p; int ix; int end; + arc *link[2], *par, *prv, *nxt; + }; + arc *root; ld sw; + beach() : sw(-1e20), root(0) { } + inline int dir(arc *x) { return x->par->link[0] != x; } + void rotate(arc *n) { + arc *p = n->par; int d = dir(n); + p->link[d] = n->link[!d]; + if (n->link[!d]) { n->link[!d]->par = p; } + n->par = p->par; + if (p->par) { p->par->link[dir(p)] = n; } + n->link[!d] = p; p->par = n; + } + void splay(arc *x, arc *f = 0) { + while (x->par != f) { + if (x->par->par == f); + else if (dir(x) == dir(x->par)) rotate(x->par); + else { rotate(x); } + rotate(x); + } + if (f == 0) { root = x; } + } + void insert(arc *n, arc *p, int d) { + splay(p); arc* c = p->link[d]; + n->link[d] = c; if (c) { c->par = n; } + p->link[d] = n; n->par = p; + arc* prv = !d ? p->prv : p; + arc* nxt = !d ? p : p->nxt; + n->prv = prv; if (prv) { prv->nxt = n; } + n->nxt = nxt; if (nxt) { nxt->prv = n; } + } + void erase(arc* n) { + arc *prv = n->prv, *nxt = n->nxt; + if (!prv && !nxt) { + if (n == root) { root = 0; } return; + } + n->prv = 0; if (prv) { prv->nxt = nxt; } + n->nxt = 0; if (nxt) { nxt->prv = prv; } + splay(n); + if (!nxt) { + root->par = n->link[0] = 0; root = prv; + } else { + splay(nxt, n); + arc* c = n->link[0]; nxt->link[0] = c; c->par = nxt; + n->link[0] = n->link[1] = nxt->par = 0; root = nxt; + } + } + bool get(arc* cur, ld &next_sweep) { + if (!cur->prv || !cur->nxt) { return 0; } + pt u = rot(cur->p - cur->prv->p); + pt v = rot(cur->nxt->p - cur->p); + if (sgn(cross(u, v)) != 1) { return 0; } + pt p = circumcenter(cur->p, cur->prv->p, cur->nxt->p); + next_sweep = p.py + abs(p - cur->p); + return 1; + } + arc* find_beachline(ld x) { + arc* cur = root; + while (cur) { + ld l = cur->prv ? + parab_intersect(cur->prv->p, cur->p, sw) : -1e30; + ld r = cur->nxt ? + parab_intersect(cur->p, cur->nxt->p, sw) : 1e30; + if (l <= x && x <= r) { splay(cur); return cur; } + cur = cur->link[x > r]; + } + return 0; + } +}; using arc = beach::arc; + +struct event { + event(ld sw, int ix) + : type(0), sw(sw), ix(ix) {} + event(ld sw, arc* c) : type(1), sw(sw), + prv(c->prv->ix), cur(c), nxt(c->nxt->ix) {} + int type, ix, prv, nxt; arc* cur; ld sw; + bool operator>(const event &l) const { return sw > l.sw; } +}; + +struct voronoi_t { + vector<pt> v; vector<vector<pt>> poly; + vector<ii> f; vector<ii> dy; +}; + +voronoi_t fortune(vector<pt> &ps) { + voronoi_t ans; beach line; + priority_queue<event, vector<event>, greater<event>> e; + + auto add_edge = [&](int u, int v, int a, int b, + arc* c1, arc* c2) { + if (c1) { c1->end = ans.dy.size()*2; } + if (c2) { c2->end = ans.dy.size()*2 + 1; } + ans.dy.emplace_back(u, v); + ans.f.emplace_back(a, b); + }; + auto write_edge = [&](int ix, int v) { + if (ix % 2 == 0) { ans.dy[ix/2].first = v; } + else { ans.dy[ix/2].second = v; } + }; + auto add_event = [&](arc* cur) { + ld nxt; if (line.get(cur, nxt)) { e.emplace(nxt, cur); } + }; + + int n = ps.size(), cnt = 0; + vector<pair<pt, int>> psi (n); + for (int i = 0; i < n; i++) + psi[i] = make_pair(ps[i], i); + + vector<arc> nodes; + nodes.reserve(n*4); + auto mknode = [&](pt p, int ix) { + nodes.emplace_back(p, ix); + return &nodes.back(); + }; + sort(psi.begin(), psi.end(), [](auto& a, auto& b) { + return make_pair(a.first.py, a.first.px) + < make_pair(b.first.py, b.first.px); + }); + vector<int> bix (n); + for (int i = 0; i < n; i++) { bix[i] = psi[i].second; } + + arc* prv = line.root = mknode(psi[0].first, 0), *no; + for (int i = 1; i < n; i++) { + if (sgn(psi[i].first.py - psi[0].first.py) == 0) { + add_edge(-1, -1, i-1, i, 0, prv); + line.insert(no = mknode(psi[i].first, i), prv, 1); + prv = no; + } else { e.emplace(psi[i].first.py, i); } + } + while (e.size()) { + event q = e.top(); e.pop(); + arc *prv, *cur, *nxt, *si; + int v = ans.v.size(), ix = q.ix; + line.sw = q.sw; + if (q.type == 0) { + pt p = psi[ix].first; + cur = line.find_beachline(p.px); + line.insert(si = mknode(p, ix), cur, 0); + line.insert(prv = mknode(cur->p, cur->ix), si, 0); + add_edge(-1, -1, cur->ix, ix, si, prv); + add_event(prv); add_event(cur); + continue; + } + + cur = q.cur, prv = cur->prv, nxt = cur->nxt; + if (!prv || !nxt || prv->ix != q.prv || + nxt->ix != q.nxt) { continue; } + ans.v.push_back(circumcenter(prv->p, nxt->p, cur->p)); + write_edge(prv->end, v); write_edge(cur->end, v); + add_edge(v, -1, prv->ix, nxt->ix, 0, prv); + line.erase(cur); + add_event(prv); add_event(nxt); + } + + ans.poly.assign(n, {}); + for (int i = 0; i < ans.dy.size(); i++) { + auto [x, y] = ans.dy[i]; + if (x == -1 || y == -1) { continue; } + ans.poly[bix[ans.f[i].first]].push_back(ans.v[x]); + ans.poly[bix[ans.f[i].second]].push_back(ans.v[x]); + ans.poly[bix[ans.f[i].first]].push_back(ans.v[y]); + ans.poly[bix[ans.f[i].second]].push_back(ans.v[y]); + } + for (int i = 0; i < ans.poly.size(); i++) + ans.poly[i] = convex_hull(ans.poly[i]); + return ans; +}