diff --git a/.gitignore b/.gitignore index a91a137cced819927f2c25cf2d63de912b63b289..da699601f6006f002460a5382a193f1c186e1536 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,9 @@ _minted* *.dvi *.synctex.gz *.aux + +testes/hld-ps +testes/fenwick-tree +testes/fenwick-2d-tree +testes/lstit +testes/monotone diff --git a/Makefile b/Makefile index 484610ce03e03371c4e960e5910e6dcdebc3b458..9f1f6cfe521701cd72e4e89a93ff510b7207036f 100644 --- a/Makefile +++ b/Makefile @@ -1,29 +1,28 @@ .PHONY: all test -all: testes/hld-ps.cpp testes/fenwick-tree.cpp testes/fenwick-2d-tree.cpp testes/lazy-segment-tree.cpp testes/convex-hull.cpp caderno.pdf +all: testes/fenwick-tree testes/fenwick-2d-tree testes/hld-ps testes/lstit testes/monotone caderno.pdf -caderno.pdf: fontes/*.cpp caderno/caderno.tex - latexmk caderno/caderno +caderno.pdf: fontes/*.cpp fontes/*.h caderno/caderno.tex + latexmk caderno/caderno -e '$$pdflatex='lualatex -shell-escape'' -test: testes/hld-ps.cpp testes/fenwick-tree.cpp testes/fenwick-2d-tree.cpp testes/lazy-segment-tree.cpp testes/convex-hull.cpp - g++ -O2 testes/hld-ps.cpp && ./a.out <testes/hld-ps.in | diff - testes/hld-ps.out - g++ -O2 testes/fenwick-tree.cpp && ./a.out - g++ -O2 testes/fenwick-2d-tree.cpp && ./a.out - g++ -O2 testes/lazy-segment-tree.cpp && ./a.out - g++ -O2 testes/convex-hull.cpp && ./a.out - rm a.out +test: testes/fenwick-tree testes/fenwick-2d-tree testes/hld-ps testes/lstit testes/monotone + ./testes/hld-ps <testes/hld-ps.in | colordiff -u - testes/hld-ps.out + ./testes/fenwick-tree + ./testes/fenwick-2d-tree + ./testes/lstit + ./testes/monotone -testes/fenwick-tree.cpp: fontes/template.cpp testes/fenwick-tree.gen fontes/fenwick-tree.cpp - testes/fenwick-tree.gen +testes/fenwick-tree: testes/fenwick-tree.cpp fontes/fenwick-tree.h + g++ -O2 testes/fenwick-tree.cpp -o testes/fenwick-tree -testes/fenwick-2d-tree.cpp: fontes/template.cpp testes/fenwick-2d-tree.gen fontes/fenwick-2d-tree.cpp - testes/fenwick-2d-tree.gen +testes/fenwick-2d-tree: testes/fenwick-2d-tree.cpp fontes/fenwick-2d-tree.h + g++ -O2 testes/fenwick-2d-tree.cpp -o testes/fenwick-2d-tree -testes/hld-ps.cpp: fontes/template.cpp testes/hld-ps.gen fontes/heavy-light-decomposition.cpp fontes/prefix-sum.cpp - testes/hld-ps.gen +testes/hld-ps: testes/hld-ps.cpp fontes/hld.h + g++ -O2 testes/hld-ps.cpp -o testes/hld-ps -testes/lazy-segment-tree.cpp: fontes/template.cpp testes/lazy-segment-tree.gen fontes/lazy-segment-tree.cpp - testes/lazy-segment-tree.gen +testes/lstit: fontes/template.cpp testes/lstit.cpp + g++ -O2 testes/lstit.cpp -o testes/lstit -testes/convex-hull.cpp: fontes/template.cpp testes/convex-hull.gen fontes/convex-hull.cpp - testes/convex-hull.gen +testes/monotone: fontes/template.cpp testes/monotone.cpp + g++ -O2 testes/monotone.cpp -o testes/monotone diff --git a/caderno.pdf b/caderno.pdf index 67cd33ccb05495ab52f90b2d585ba956b99027ce..ec8f0d360fd18a194fae9d1448a4269a19a65092 100644 Binary files a/caderno.pdf and b/caderno.pdf differ diff --git a/caderno/caderno.tex b/caderno/caderno.tex index 51cde7895198889800e88a1a5c8e189407c8d0e9..116c6e61665146a51579362b37759e57decdc148 100644 --- a/caderno/caderno.tex +++ b/caderno/caderno.tex @@ -1,6 +1,5 @@ -\documentclass[titlepage]{article} -\usepackage[margin=1cm,footskip=.5cm]{geometry} -\usepackage[utf8]{inputenc} +\documentclass[titlepage,a4paper]{article} +\usepackage[margin=1cm,bmargin=2cm,footskip=1cm]{geometry} \usepackage{minted} \usepackage[T1]{fontenc} \usemintedstyle{vs} @@ -8,41 +7,53 @@ \usepackage[brazilian]{babel} \usepackage{lmodern} \usepackage{amsmath} -\inputencoding{utf8} +\usepackage{caption} +\usepackage{multirow} +\usepackage{fontspec} +\usepackage{hyperref} +\setmonofont{Fantasque Sans Mono} \newcommand{\bigO}{\mathcal{O}} -\newcommand{\importsource}[2][cpp]{\inputminted[linenos]{#1}{fontes/#2}} +\newcommand{\importsource}[2][cpp]{ + \footnotesize + \inputminted[linenos, xleftmargin=\parindent]{#1}{fontes/#2} +} \begin{document} +\twocolumn -\title{Caderno de Maratona} +\title{Caderno de Maratona de Programação} \author{Fernando Kiotheka$^1$} -\date{% - $^1$Universidade Federal do Paraná\\[2ex] - \today -} +\date{$^1$Universidade Federal do Paraná\\[2ex]\today} \maketitle -%\tableofcontents -\newpage - -\section{C++} - -\begin{multicols}{2} -\subsection{Esboços} -\importsource{template.cpp} -.bashrc -\importsource[bash]{bashrc} -.vimrc -\importsource[vim]{vimrc} -stress.sh -\importsource[bash]{stress.sh} -gen.cpp -\importsource{gen.cpp} -\end{multicols} +\tableofcontents +\begin{table*} +\centering + \begin{tabular}{lll} + \hline + $n$ & Pior algoritmo que passa & Comentário \\ \hline + $\leq [10..11]$ & $\bigO(n!)$, $\bigO(n^6)$ & ex. Enumerar permutações \\ + $\leq [15..18]$ & $\bigO(2^n n^2)$ & ex. PD do Caixeiro-Viajante \\ + $\leq [18..22]$ & $\bigO(2^n n)$ & ex. PD com técnica de máscara de bits \\ + $\leq 100$ & $\bigO(n^4)$ & ex. PD com 3 dimensões + laço $\bigO(n)$, $_{n}C_{k=4}$ \\ + $\leq 400$ & $\bigO(n^3)$ & ex. Floyd-Warshall \\ + $\leq 2\cdot 10^3$ & $\bigO(n^2 \lg n)$ & ex. 2 laços aninhados + consulta em árvore \\ + $\leq 5\cdot 10^4$ & $\bigO(n^2)$ & ex. Bubble/Selection/Insertion Sort \\ + $\leq 10^5$ & $\bigO(n \lg^2 n) = \bigO((\lg n)(\lg n))$ & ex. Construção de vetor de sufixos padrão \\ + $\leq 10^6$ & $\bigO(n \lg n)$ & ex. Merge Sort, construir árvore de segmento \\ + $\leq 10^7$ & $\bigO(n \lg \lg n)$ & ex. Crivo de Eratóstenes, função totiente \\ + $\leq 10^8$ & $\bigO(n)$, $\bigO(\lg n)$, $\bigO(1)$ & ex. Solução matemática. Maioria dos problemas tem $n \leq 10^9$ (gargalo de E/S) \\ + \hline + \end{tabular} + \caption*{$10^8$ operações por segundo.} +\end{table*} -\subsection{Comparações} -\begin{multicols}{2} +\newpage +\section{Teoria} +\subsection{Comparações algorítmicas} +\begin{table}[ht] + \centering \begin{tabular}{l|r} \hline $\lg 10$ (\texttt{1E1}) & 2.3 \\ @@ -58,9 +69,14 @@ gen.cpp $\lg 100000000000$ (\texttt{1E10}) & 25.3 \\ $\lg 1000000000000$ (\texttt{1E11}) & 27.6 \\ $\lg 10000000000000$ (\texttt{1E12}) & 29.9 \\ + $2^{10}$ & $\approx 10^{3}$ \\ + $2^{20}$ & $\approx 10^{6}$ \\ \hline \end{tabular} +\end{table} +\begin{table}[ht] + \centering \begin{tabular}{crcccc} \hline Sinal & Tipo & Bits & Máximo & Dígitos \\ @@ -77,43 +93,11 @@ gen.cpp $+$ & \texttt{\_\_int128} & 128 & $\approx 3 \cdot 10^{38}$ & 38 \\ \hline \end{tabular} +\end{table} - \begin{tabular}{r|l} - \hline - Valor & Estimativa \\ - \hline - $2^{10}$ & $10^{3}$ \\ - $2^{20}$ & $10^{6}$ \\ - \hline - \end{tabular} -\end{multicols} - -Estimativa computacional: $10^8$ operações por segundo. - -\begin{center} - \begin{tabular}{lll} - \hline - $n$ & Pior algoritmo que passa & Comentário \\ \hline - $\leq [10..11]$ & $\bigO(n!)$, $\bigO(n^6)$ & ex. Enumerar permutações \\ - $\leq [15..18]$ & $\bigO(2^n n^2)$ & ex. PD do Caixeiro-Viajante \\ - $\leq [18..22]$ & $\bigO(2^n n)$ & ex. PD com técnica de máscara de bits \\ - $\leq 100$ & $\bigO(n^4)$ & ex. PD com 3 dimensões + laço $\bigO(n)$, $_{n}C_{k=4}$ \\ - $\leq 400$ & $\bigO(n^3)$ & ex. Floyd-Warshall \\ - $\leq 2\cdot 10^3$ & $\bigO(n^2 \lg n)$ & ex. 2 laços aninhados + consulta em árvore \\ - $\leq 5\cdot 10^4$ & $\bigO(n^2)$ & ex. Bubble/Selection/Insertion Sort \\ - $\leq 10^5$ & $\bigO(n \lg^2 n) = \bigO((\lg n)(\lg n))$ & ex. Construção de vetor de sufixos padrão \\ - $\leq 10^6$ & $\bigO(n \lg n)$ & ex. Merge Sort, construir árvore de segmento \\ - $\leq 10^7$ & $\bigO(n \lg \lg n)$ & ex. Crivo de Eratóstenes, função totiente \\ - $\leq 10^8$ & $\bigO(n)$, $\bigO(\lg n)$, $\bigO(1)$ & ex. Solução matemática. Maioria dos problemas tem $n \leq 10^9$ (gargalo de E/S) \\ - \hline - \end{tabular} -\end{center} - -\newpage -\section{Matemática} -\begin{multicols}{2} +\subsection{Progressões} \begin{align*} - a_n = a_k + r(n - k) + a_n = a_k + r(n - k) \\ a_n = a_k q^{(n-k)} \end{align*} \begin{itemize} @@ -125,149 +109,469 @@ Estimativa computacional: $10^8$ operações por segundo. S_n = \frac{n(a_1 + a_n)}{2} \\ 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*} -\end{multicols} -\section{Algoritmos} -\begin{multicols}{2} - \importsource{merge-sort.cpp} -\end{multicols} +\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$. -\section{Estrutura de Dados} +\subsection{Teoremas de Fermat} +\begin{align*} + a^p = a \pmod{p} \\ + a^{p-1} = 1 \pmod{p} \\ + (a + b)^p = a^p + b^p \pmod{p} \\ + a^{-1} = a^{p-2} \pmod{p} +\end{align*} +onde $p$ é primo. -\subsection{Pilha/Fila mínima} -\begin{multicols}{2} - \importsource{min-stack.cpp} - \importsource{min-queue.cpp} - \importsource{min-queue-2.cpp} - \importsource{min-queue-3.cpp} - \importsource{custom-hash.cpp} -\end{multicols} - -\subsection{LIS} -\begin{multicols}{2} -\importsource{lis.cpp} -\importsource{lisnlgn.cpp} -\end{multicols} +\subsection{Módulo no expoente} +\begin{align*} + a^n = a^{n \pmod{\phi(m)}} \pmod{m} +\end{align*} +para $a$ e $m$ coprimos. -\subsection{DP on broken profile} +\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*} + +\section{C++} + +\subsection{Esboço} +\importsource{template.cpp} +\subsection{Bashrc} +\importsource[bash]{bashrc} +\subsection{Vimrc} +\importsource[vim]{vimrc} +\subsection{Teste de estresse} +\importsource[bash]{stress.sh} +\subsection{Gerador} +\importsource{gen.cpp} + +\section{Estrutura de Dados} +\subsection{Soma de prefixos} +\importsource{prefix-sum.h} \subsection{Árvore de Fenwick} -\begin{multicols}{2} -\importsource{fenwick-tree.cpp} -\end{multicols} +\begin{tabular}{l|l|l} + \hline + 1-indexada & + Atualização $\bigO(\lg n)$ & + Consulta $\bigO(\lg n)$ \\ + \hline +\end{tabular} + +\vspace{4pt} +\noindent +\begin{tabular}{lll} + \hline + \textbf{Atualização} & \textbf{Consulta} & \textbf{Funções} \\ \hline + Ponto & Intervalo & \texttt{add} + \texttt{sum\_inclusive} \\ + Intervalo & Ponto & \texttt{add\_inclusive} + \texttt{pref} \\ + \hline +\end{tabular} + +\importsource{fenwick-tree.h} \subsection{Árvore de Fenwick 2D} -\begin{multicols}{2} -\importsource{fenwick-2d-tree.cpp} -\end{multicols} +\begin{tabular}{l|l|l} + \hline + 1-indexada & + Atualização $\bigO(\lg^2 n)$ & + Consulta $\bigO(\lg^2 n)$ \\ + \hline +\end{tabular} + +\importsource{fenwick-2d-tree.h} + +\subsection{Árvore de Fenwick intervalar} +\begin{tabular}{l|l|l} + \hline + 1-indexada & + Atualização $\bigO(\lg n)$ & + Consulta $\bigO(\lg n)$ \\ + \hline +\end{tabular} + +\importsource{fenwick-range-tree.h} + +\subsection{União-busca} +\importsource{disjoint.h} + +\subsection{Pilha mínima} +\importsource{min-stack.h} + +\subsection{Fila mínima (sabendo o que remover)} +\importsource{min-queue.h} + +\subsection{Fila mínima} +\importsource{min-queue-2.h} + +\subsection{Fila mínima (guarda os elementos)} +\importsource{min-queue-3.h} + +\subsection{Maior elemento anterior} +\importsource{pge.h} + +\subsection{Menor elemento anterior} +\importsource{ple.h} + +\subsection{Próximo maior elemento} +\importsource{nge.h} + +\subsection{Próximo menor elemento} +\importsource{nle.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 + \multicolumn{3}{l}{1-indexada} \\ \hline + Construção $\bigO(n)$ & + Atualização $\bigO(\lg n)$ & + Consulta $\bigO(\lg n)$ \\ + \hline +\end{tabular} -\subsection{Árvore de Segmentos Preguiçosa} -\begin{center} -\begin{tabular}{c|c|c|c} +\vspace{4pt} +\noindent +\begin{tabular}{cccc} \hline - Macro & RSQ & RMQ & RMaxQ \\ \hline - \texttt{LST\_OP(X, Y)} & \texttt{(X + Y)} & \texttt{min(X, Y)} & \texttt{max(X, Y)} \\ - \texttt{LST\_NEUTRAL} & 0 & \texttt{numeric\_limits<int>::max()} & \texttt{numeric\_limits<int>::min()} \\ - \texttt{LST\_FACTOR} & \texttt{(tb - ta + 1)} & \texttt{1} & \texttt{1} \\ + Macro & + & mín & máx \\ \hline + \texttt{OP(X, Y)} & \texttt{((X) + (Y))} & \texttt{min(X, Y)} & \texttt{max(X, Y)} \\ + \texttt{NEUTRAL} & 0 & \texttt{oo} & \texttt{-oo} \\ + \texttt{FACTOR} & \texttt{(tb - ta + 1)} & \texttt{1} & \texttt{1} \\ \hline \end{tabular} -\end{center} -\begin{multicols}{2} -\importsource{lazy-segment-tree.cpp} -\end{multicols} + +\importsource{strec.h} + +\subsection{Árvore de segmentos iterativa} +\importsource{stit.h} + +\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} \section{Grafos} -\subsection{Busca} -\subsubsection{Busca em Profundidade -- DFS (Depth First Search)} -\importsource{dfs.cpp} +\subsection{Articulações e Pontes} +\importsource{articbridges.h} + +\subsection{Stoer-Wagner} +\importsource{stoer-wagner.h} + +\subsection{SPFA*} + +\subsection{BFS 0-1} +\importsource{bfs01.h} -\subsubsection{Conectado} +\subsection{Emparelhamento estável} +\begin{tabular}{l} + \hline + $\bigO(n^2)$ \\ + \hline +\end{tabular} +\importsource{stable-matching.h} + +\subsection{Fluxo máximo*} + +\subsection{Fluxo de custo mínimo*} + +\subsection{Busca em profundidade recursiva} +\importsource{dfsrec.h} + +\subsection{Busca em profundidade com pilha} +\importsource{dfsstack.h} + +\subsection{Busca em largura} +\importsource{bfs.h} + +\subsection{Conectado*} \importsource{connected.cpp} -\subsubsection{Componentes Fortemente Conectados -- Tarjan} +\subsection{Componentes fortes -- Tarjan*} \importsource{tarjan.cpp} -\subsubsection{Componentes Fortemente Conectados -- Kosaraju} +\subsection{Componentes fortes -- Kosaraju*} \importsource{kosaraju.cpp} -\subsection{Caminhos} -\subsubsection{Caminho Mínimo com Pesos Não-Negativos -- Dijkstra} -\importsource{dijkstra.cpp} +\subsection{Caminho mínimo -- Dijkstra} +\importsource{dijkstra.h} -\subsubsection{Caminho Mínimo -- Bellman-Ford} +\subsection{Caminho mínimo -- Bellman-Ford*} \importsource{bellman-ford.cpp} -\subsubsection{Todos os Caminhos Mínimos (Programação Dinâmica) -- Floyd-Warshall} +\subsection{Caminhos mínimos -- Floyd-Warshall*} \importsource{floyd-warshall.cpp} -\subsubsection{Ordenação Topológica -- Topological Sorting} -\importsource{topological-sort.cpp} +\subsection{Ordenação Topológica} +\importsource{topo.h} -\subsection{Árvores, LCA, Decomposições} +\subsection{Árvore geradora mínima -- Prim} +\importsource{prim.h} -\subsubsection{Árvore Geradora Mínima -- Prim} -\importsource{prim.cpp} +\subsection{Árvore geradora mínima -- Kruskal} +\importsource{kruskal.h} -\subsubsection{Ascensão Binária -- Binary Lifting} -\begin{multicols}{2} +\subsection{Ascensão binária*} \importsource{binary-lifting.cpp} -\end{multicols} -\subsubsection{Decomposição Pesado-Leve -- Heavy-Light Decomposition} -\begin{multicols}{2} -\importsource{heavy-light-decomposition.cpp} -\end{multicols} +\subsection{Menor anc. comum -- Ancensão binária*} -\subsubsection{Decomposição Raíz Quadrada de Árvore -- Square Root Tree Decomposition} -\importsource{square-root-tree-decomposition.cpp} +\subsection{Menor anc. comum -- Dec. pesado-leve*} -\section{Geometria} - -\subsection{Fecho Convexo (Corrente Monótona) -- Convex Hull (Monotone Chain)} -\begin{center} -\begin{tabular}{c|c|c|c|c} +\subsection{Decomposição pesado-leve} +\begin{tabular}{l|l} + \hline + \multicolumn{2}{l}{ + Precisa de soma de prefixos/árvore de segmentos preguiçosa + } \\ \hline + \multicolumn{2}{l}{ + Se usado com pesos nos vértices, use com $\texttt{edge\_wei} = 0$ + } \\ \hline + Construção $\bigO(|V|\lg|V| + |E|)$ & + Atualização/Consulta $\bigO(\lg^2 n)$ \\ \hline - & \textbf{Anti-horário} & Horário & Anti-horário Colinear & Horário Colinear \\ \hline - Operação & \texttt{>} & \texttt{<} & \texttt{>=} & \texttt{<=} \\ \hline \end{tabular} -\end{center} -\begin{multicols}{2} -\importsource{convex-hull.cpp} -\end{multicols} +\importsource{hld.h} + +\subsection{Decomposição raiz quadrada de árvore} +\importsource{stdt.h} -\subsection{Sweep angular} -\importsource{angular-sweep.cpp} +\subsection{Menor anc. comum -- Dec. raiz quad.} +\importsource{stdtlca.h} + +\subsection{Empar. máximo bipartido -- Kuhn*} + +\subsection{Empar. máximo bipartido -- Hopcroft*} \section{Matemática} -\subsection{Crivo de Eratóstenes} +\subsection{Problema de Josephus} + +\subsection{Operações comuns} +\importsource{numbers.h} + +\subsection{Primeiros e últimos digitos de $n^k$} +\importsource{nk-first-last-digits.h} + +\subsection{Triângulo de Pascal} +\importsource{pascal-triangle.h} + +\subsection{2-SAT*} + +\subsection{Inclusão-Exclusão} +\importsource{inclusion-exclusion.h} + +\subsection{Mínimo excluído com conjunto} +\importsource{mexset.h} + +\subsection{Mínimo excluído} +\importsource{mex.h} + +\subsection{Nímero*} + +\subsection{Euclides estendido/inv. multiplicativo} +\begin{tabular}{l} + \hline +$\bigO(\lg \min(a, b))$ \\ +\hline +\end{tabular} +\begin{align*} + ax + by &= \gcd(a, b) \\ + ax &= gcd(a, b) \pmod{b} \\ + (\gcd(a, b) = 1) &\implies (ax = 1 \pmod{b}) +\end{align*} +\importsource{extgcd.h} + +\subsection{Detecção de ciclo} +\importsource{floyd.h} + +\subsection{Equação diofantina linear} +\begin{align*} +ax + by = c +\end{align*} +\importsource{diophantine.h} + +\subsection{Multiplicação -- Karatsuba*} + +\subsection{Números de Catalão} +\importsource{catalan.h} + +\subsection{Fatoração por tentativa} +\begin{tabular}{l} + \hline + $\bigO(\sqrt{n})$ \\ +\hline +\end{tabular} +\importsource{factorize.h} + +\subsection{Crivo de Eratóstenes*} \importsource{sieve-of-eratosthenes.cpp} -\subsection{Exponenciação rápida} -\importsource{fast-pow.cpp} +\subsection{Exponenciação binária*} +\importsource{binary-pow.h} -\subsection{Exponenciação de matrizes} +\subsection{Exponenciação de matrizes*} \importsource{matrix-mult.cpp} -\subsection{Algoritmo de euclides estendido} -\importsource{extended-gcd.cpp} +\subsection{Miller-Rabin*} -\section{Máscaras de Bit e Operações em Bit} -\importsource{bit-ops.cpp} +\subsection{Pollard Rho*} + +\subsection{Teorema chinês do resto*} + +\subsection{Totiente de Euler*} +\importsource{euler-totient.h} + +\subsection{Fibonacci*} + +\subsection{Teorema chinês do resto generalizado*} \section{Strings} +\subsection{Árvore de sufixos} +\importsource{suffix-tree.h} + +\subsection{Aho-Corasick*} +\importsource{acs.h} + +\subsection{Algoritmo Z*} + +\subsection{Autômato de Sufixo*} + \subsection{KMP} -\importsource{kmp.cpp} +\begin{tabular}{l|l} + \hline + Pré-computação $\bigO(m)$ & + Busca $\bigO(n + m)$ \\ + \hline +\end{tabular} +\importsource{kmp.h} + +\subsection{Autômato KMP*} + +\subsection{Rabin-Karp} +\importsource{rabinkarp.h} + +\subsection{Vetor de sufixos*} + +\subsection{Vetor de sufixos com ordenação por contagem*} + +\subsection{Trie} +\importsource{trie.h} + +\section{Geometria} + +\subsection{Pontos} +\importsource{point.h} + +\subsection{Fecho convexo com corrente monotônica} +\begin{tabular}{l} + \hline + $\bigO(n \lg n)$ \\ + \hline +\end{tabular} +\importsource{monotone.h} + +\subsection{Fecho convexo de Graham} +\begin{tabular}{l} + \hline + $\bigO(n \lg n)$ \\ + \hline +\end{tabular} +\importsource{graham.h} + +\subsection{Interseção de retângulos*} + +\subsection{Polígono é convexo?*} + +\subsection{Ponto dentro do polígono?*} + +\subsection{Área de polígono*} -\section{Outros} +\subsection{Área de polígono de pontos inteiros*} -\subsection{Busca binária} +\subsection{Distância de segmento e segmento*} + +\subsection{Distância de ponto e segmento*} + +\subsection{Intersecção de segmento*} + +\subsection{Árvore KD} +\importsource{kd-tree.h} + +\subsection{Varredura linear*} + +\subsection{Varredura angular} +\importsource{angular-sweep.h} + +\section{Problemas} +\subsection{Rainhas no tabuleiro*} + +\subsection{Jogo de Nim*} + +\subsection{Soma em subvetor*} + +\subsection{Remoção de valores com deque*} + +\subsection{Remoção de valores com lista*} + +\subsection{Embarcadouro*} + +\section{Algoritmos} +\subsection{Ordenação por fusão*} +\importsource{merge-sort.h} + +\subsection{Mochila com recuperação*} + +\subsection{Permutações*} + +\subsection{Algoritmo de Mo*} + +\subsection{Meet in the middle*} + +\subsection{Maior subsequência crescente*} +\importsource{lis.cpp} + +\subsection{Maior subsequência crescente mais rápido*} +\importsource{lisnlgn.cpp} + +\subsection{PD de perfil quebrado*} + +\subsection{Busca binária*} \importsource{binary-search.cpp} +\subsection{Busca binária diferentona*} + +\subsection{Máscaras de bit e operações em bit*} +\importsource{bit-ops.cpp} + \end{document} diff --git a/fontes/acs.h b/fontes/acs.h new file mode 100644 index 0000000000000000000000000000000000000000..4357d14f88e0dda436c0135bdc5bc90b2506609e --- /dev/null +++ b/fontes/acs.h @@ -0,0 +1,67 @@ +struct node { + int p, pc, depth, lnk, out, occ; + bool leaf; + vector<int> nxt, go, ix; + + node() : p (0), pc (0), depth (-1), + lnk (-1), out (-1), occ (0), + leaf (false), nxt (S, -1), go (S, -1) {} +}; + +vector<node> aca (1); +void ins(string ne, int ix) { + 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(); + node n; n.p = u; n.pc = ch; n.depth = i; + aca.push_back(n); + } + u = aca[u].nxt[ch]; + } + aca[u].leaf = true; + aca[u].ix.push_back(ix); +} + +int go(int u, int c); + +int link(int u) { + if (aca[u].lnk != -1) { return aca[u].lnk; } + if (u == 0 || aca[u].p == 0) { return aca[u].lnk = 0; } + return aca[u].lnk = go(link(aca[u].p), aca[u].pc); +} + +int go(int u, int c) { + if (aca[u].go[c] != -1) { return aca[u].go[c]; } + if (aca[u].nxt[c] != -1) + return aca[u].go[c] = aca[u].nxt[c]; + if (u == 0) { return aca[u].go[c] = 0; } + return aca[u].go[c] = go(link(u), c); +} + +int out(int u) { + if (aca[u].out != -1) { return aca[u].out; } + int v = link(u); + if (v == 0 || aca[v].leaf) { return aca[u].out = v; } + return aca[u].out = out(v); +} + +vector<int> occ (N); vector<vector<int>> occix (N); +void process(string hay) { + int u = 0; + for (int i = 0; i < hay.size(); i++) { + int ch = to_i(hay[i]); + u = go(u, ch); + for (int v = u; v != 0; v = out(v)) { + for (auto ix : aca[v].ix) + // match at (i - aca[v].depth), O(len + ans) + occix[ix].push_back(i - aca[v].depth); + aca[v].occ++; + } + } + for (int u = 0; u < aca.size(); u++) + for (auto ix : aca[u].ix) + // number of matches, O(len) + occ[ix] += aca[u].occ; +} diff --git a/fontes/aho-cora-sick.cpp b/fontes/aho-cora-sick.cpp deleted file mode 100644 index 3a74c2a655f249a80dbac448f8e172d891ccfe1c..0000000000000000000000000000000000000000 --- a/fontes/aho-cora-sick.cpp +++ /dev/null @@ -1,70 +0,0 @@ -struct node { - int p = 0, pc = 0; - int oix = -1, lnk = -1, out = -1; - bool leaf = false; - vector<int> nxt = vector<int>(256, -1); - vector<int> go = vector<int>(256, -1); - vector<int> ix; - int occ; -}; - -vector<node> aca = { node() }; -vector<vector<int>> occ (100000+15); - -void insert(string needle, int ix) { - int u = 0; - for (int i = 0; i < needle.size(); i++) { - int ch = to_i(needle[i]); - if (aca[u].nxt[ch] == -1) { - aca[u].nxt[ch] = aca.size(); - node n; n.p = u; n.pc = ch; n.oix = i; - aca.push_back(n); - } - u = aca[u].nxt[ch]; - } - aca[u].leaf = true; - aca[u].ix.push_back(ix); -} - -int go(int u, int c); - -int link(int u) { - if (aca[u].lnk != -1) { return aca[u].lnk; } - if (u == 0 || aca[u].p == 0) { return aca[u].lnk = 0; } - return aca[u].lnk = go(link(aca[u].p), aca[u].pc); -} - -int go(int u, int c) { - if (aca[u].go[c] != -1) { return aca[u].go[c]; } - if (aca[u].nxt[c] != -1) { return aca[u].go[c] = aca[u].nxt[c]; } - if (u == 0) { return aca[u].go[c] = 0; } - return aca[u].go[c] = go(link(u), c); -} - -int out(int u) { - if (aca[u].out != -1) { return aca[u].out; } - int v = link(u); - if (v == 0 || aca[v].leaf) { return aca[u].out = v; } - return aca[u].out = out(v); -} - -void process(string haystack) { - int u = 0; - for (int i = 0; i < haystack.size(); i++) { - int ch = to_i(haystack[i]); - u = go(u, ch); - for (int v = u; v != 0; v = out(v)) { - for (auto ix : aca[v].ix) { - // match at (i - aca[v].oix), O(len + ans) - occ[ix].push_back(i - aca[v].oix); - } - aca[v].occ++; - } - } - for (int u = 0; u < aca.size(); u++) { - for (auto ix : aca[v].ix) { - // number of matches, O(len) - occ[ix] += aca[u].occ; - } - } -} diff --git a/fontes/angular-sweep.cpp b/fontes/angular-sweep.cpp deleted file mode 100644 index 2c00d469bbb0903f5535787e58fe6ac4542841ee..0000000000000000000000000000000000000000 --- a/fontes/angular-sweep.cpp +++ /dev/null @@ -1,20 +0,0 @@ -int get_points_inside (int i, double radius, int N) { - vector<db> angles; - - for (int j = 0; j < N; j++) if (i != j && distances[i][j] <= 2*radius) { - double A = atan2(points[j].yy - points[i].yy, points[j].xx - points[i].xx); - double B = acos(distances[i][j]/(2*radius)); - angles.push_back(dbi(A - B, j)); - angles.push_back(dbi(A + B, j)); - } - - sort(angles.begin(), angles.end()); - - int count = 1, res = 1; - for (auto angle : angles) { - count += angle.second ? 1 : -1; - res = max(res, count); - } - - return res; -} diff --git a/fontes/angular-sweep.h b/fontes/angular-sweep.h new file mode 100644 index 0000000000000000000000000000000000000000..0eee34be1519a0230ae60ff3646f7a1a66b26444 --- /dev/null +++ b/fontes/angular-sweep.h @@ -0,0 +1,20 @@ +int get_points_inside (int i, double r, int n) { + vector<double> ang; + for (int j = 0; j < n; j++) + if (i != j && d[i][j] <= 2*r) { + double a = atan2(p[j].py - p[i].py, p[j].px - p[i].px); + double b = acos(d[i][j]/(2*r)); + ang.push_back(dbi(a - b, j)); + ang.push_back(dbi(a + b, j)); + } + + sort(ang.begin(), ang.end()); + + int count = 1, res = 1; + for (auto angle : ang) { + count += angle.second ? 1 : -1; + res = max(res, count); + } + + return res; +} diff --git a/fontes/articbridges.h b/fontes/articbridges.h new file mode 100644 index 0000000000000000000000000000000000000000..46d17b9c6891265716f4dbcca95826df1914c304 --- /dev/null +++ b/fontes/articbridges.h @@ -0,0 +1,18 @@ +int tk = 0; vector<int> tin (N, -1), low (N); +vector<ii> brid; set<int> arti; + +void dfs(int u, int p) { + tin[u] = low[u] = tk++; int ch = 0; + for (auto v : g[u]) { + if (v == p) continue; + else if (tin[v] == -1) { + dfs(v, u); ch++; + if ((low[v] >= tin[u] && p != u) || + (ch >= 2 && p == u)) + arti.insert(u); + if (low[v] > tin[u]) + brid.push_back(ii(u, v)); + low[u] = min(low[u], low[v]); + } else { low[u] = min(low[u], tin[v]); } + } +} diff --git a/fontes/articulations-and-bridges.cpp b/fontes/articulations-and-bridges.cpp deleted file mode 100644 index 69b9a7835486b0ee5e1dfa1a84cdb216986eca84..0000000000000000000000000000000000000000 --- a/fontes/articulations-and-bridges.cpp +++ /dev/null @@ -1,35 +0,0 @@ -vector<bool> visited (N, false); -vector<int> parent (N, -1); -vector<int> low (N); -vector<int> tin (N); -vector<ii> brid; -set<int> arti; - -void dfs(int u) { - int children = 0; - visited[u] = true; - - for (int v : graph[u]) if (!visited[v]) { - children++; - parent[v] = u; - - low[v] = tin[v] = tin[u] + 1; - dfs(v); - low[u] = min(low[u], low[v]); - - if ((parent[u] == -1 && children > 1) || - (parent[u] != -1 && low[v] >= tin[u])) - arti.insert(u); - - if (low[v] > tin[u]) - brid.push_back(ii(u, v)); - - } else if (parent[u] != v) { - low[u] = min(low[u], tin[v]); - } -} - -for (int u = 0; u < n; u++) if (!visited[u]) { - tin[u] = 0; - dfs(u); -} diff --git a/fontes/bashrc b/fontes/bashrc index 444c3483ddfa38448afbb77f65b1e82b3ef5c6b3..6e16fbe52693471332682aeae5cf71b4435d73e3 100644 --- a/fontes/bashrc +++ b/fontes/bashrc @@ -1,9 +1,9 @@ xmodmap -e 'clear lock' -e 'keycode 66=Escape' alias e=vim function bc { - boca-submit-run user password $1 C++17 $1.cpp + boca-submit-run user password $1 C++17 $1.cpp } alias bs='boca-submit-run user password' function c { - g++ -static -O2 -lm $1 && ./a.out + g++ -static -O2 -lm $1 && ./a.out } diff --git a/fontes/bfs.h b/fontes/bfs.h new file mode 100644 index 0000000000000000000000000000000000000000..97c924bb8cc97d5cbb593facfa1d5f49ac7476b7 --- /dev/null +++ b/fontes/bfs.h @@ -0,0 +1,14 @@ +int explore(int u) { + int c = 0; + queue<int> q; + q.push(u); + while (!q.empty()) { + int u = q.front(); q.pop(); + for (int v : g[u]) if (!visited[v]) { + c++; + visited[v] = true; + q.push(v); + } + } + return c; +} diff --git a/fontes/bfs01.h b/fontes/bfs01.h new file mode 100644 index 0000000000000000000000000000000000000000..ccb136133291fc23fc7e8f9bb9fe413ba60b40cd --- /dev/null +++ b/fontes/bfs01.h @@ -0,0 +1,20 @@ +vector<int> d (N, oo); + +void bfs01(int s) { + d[s] = 0; + deque<int> q; + q.push_front(s); + while (!q.empty()) { + int u = q.front(); + q.pop_front(); + for (auto [v, w] : g[u]) { + if (d[u] + w < d[v]) { + d[v] = d[u] + w; + if (w == 1) + q.push_back(v); + else + q.push_front(v); + } + } + } +} diff --git a/fontes/fast-pow.cpp b/fontes/binary-pow.h similarity index 100% rename from fontes/fast-pow.cpp rename to fontes/binary-pow.h diff --git a/fontes/bllca.h b/fontes/bllca.h new file mode 100644 index 0000000000000000000000000000000000000000..4bcd8b2e9966c3c319b5c500617103e7b0f88c14 --- /dev/null +++ b/fontes/bllca.h @@ -0,0 +1,10 @@ +int bl_lca(int a, int b) { + if (!(depth[b] < depth[a])) { swap(a, b); } + int diff = depth[a] - depth[b]; + for (int l = L; l >= 0; l--) if (diff & (1 << l)) + a = up[a][l]; + if (a == b) { return a; } + for (int l = L; l >= 0; l--) if (up[a][l] != up[b][l]) + a = up[a][l], b = up[b][l]; + return up[a][0]; +} diff --git a/fontes/catalan.cpp b/fontes/catalan.h similarity index 100% rename from fontes/catalan.cpp rename to fontes/catalan.h diff --git a/fontes/convex-hull.cpp b/fontes/convex-hull.cpp deleted file mode 100644 index d455b8a6ac5fcce45e064b503bd9058b78020fd6..0000000000000000000000000000000000000000 --- a/fontes/convex-hull.cpp +++ /dev/null @@ -1,30 +0,0 @@ -int sgn (double v) { return (v > 0) - (v < 0); } -// -1 (cw), 0 (colinear), +1 (ccw) -int seg_ornt (pt a, pt b, pt c) { - return sgn(cross(vec(a, b), vec(a, c))); -} - -// doesn't include collinear points (<= -> < to include) -vpt convex_hull /* O(n lg n) */ (vpt& ps) { - int k = 0, n = ps.size(); - vpt result (n * 2); - - sort(all(ps), [](pt a, pt b) { - return mp(a.px, a.py) < mp(b.px, b.py); - }); - - for (int i = 0; i < n; i++) { - while (k >= 2 && seg_ornt( /* lower hull */ - result[k-2], result[k-1], ps[i]) <= 0) k--; - result[k++] = ps[i]; - } - - for (int i = n - 2, t = k + 1; i >= 0; i--) { - while (k >= t && seg_ornt( /* upper hull */ - result[k-2], result[k-1], ps[i]) <= 0) k--; - result[k++] = ps[i]; - } - - result.resize(k - 1); - return result; -} diff --git a/fontes/custom-hash.cpp b/fontes/custom-hash.h similarity index 100% rename from fontes/custom-hash.cpp rename to fontes/custom-hash.h diff --git a/fontes/dfs.cpp b/fontes/dfs.cpp deleted file mode 100644 index 4ec532c36a7d0219fe43b922b93e8f9fe0d4a420..0000000000000000000000000000000000000000 --- a/fontes/dfs.cpp +++ /dev/null @@ -1,15 +0,0 @@ -int dfs (int u, int parent, int dest, int w) { - if (u == dest) { return w; } - - for (auto e : prim_graph[u]) if (e.vv != parent) { - int returned_weight = dfs(e.vv, u, dest, e.ww); - if (returned_weight != -oo) { return max(returned_weight, w); } - } - - return -oo; -} - -int find_max_weight (int u, int v) { - if (u == v) { return 0; } - return dfs(u, -1, v, -oo); -} diff --git a/fontes/dfsrec.h b/fontes/dfsrec.h new file mode 100644 index 0000000000000000000000000000000000000000..04b2dde8d72ce281d6fda4336e2d19bb21d1628d --- /dev/null +++ b/fontes/dfsrec.h @@ -0,0 +1,7 @@ +int explore(int u) { + visited[u] = true; + int c = 1; + for (int v : g[u]) if (!visited[v]) + c += explore(v); + return c; +} diff --git a/fontes/dfsstack.h b/fontes/dfsstack.h new file mode 100644 index 0000000000000000000000000000000000000000..3b8e6be2b217a36f1beb502b127b3b864ea1f73e --- /dev/null +++ b/fontes/dfsstack.h @@ -0,0 +1,14 @@ +int explore(int u) { + int c = 0; + stack<int> s; + s.push(u); + while (!s.empty()) { + int u = s.top(); s.pop(); + for (int v : g[u]) if (!visited[v]) { + c++; + visited[v] = true; + s.push(v); + } + } + return c; +} diff --git a/fontes/dijkstra.cpp b/fontes/dijkstra.cpp deleted file mode 100644 index bc007100d852d2fc3919a7caaaf819c4435b81a2..0000000000000000000000000000000000000000 --- a/fontes/dijkstra.cpp +++ /dev/null @@ -1,37 +0,0 @@ -vvii graph (N); -vi dist (N); -vector<bool> visited (N); - -int dijkstra (int source, int destination, int n) { - fill(dist.begin(), dist.begin() + n, oo); - fill(visited.begin(), visited.begin() + n, false); - priority_queue<ii, vii, greater<ii>> Q; - - dist[source] = 0; - Q.push({0, source}); - - while (!Q.empty()) { - int u = Q.top().uu; Q.pop(); - if (visited[u]) { continue; } - visited[u] = true; - - for (auto e : invgraph[u]) { - int v = e.vv, w = e.ww; - if (dist[u] == dist[v] + w) { - dag[v].push_back(u); - } - } - - if (u == destination) { break; } - - for (auto e : graph[u]) { - int v = e.vv, w = e.ww; - if (dist[v] > dist[u] + w) { - dist[v] = dist[u] + w; - Q.push({dist[v], v}); - } - } - } - - return dist[destination]; -} diff --git a/fontes/dijkstra.h b/fontes/dijkstra.h new file mode 100644 index 0000000000000000000000000000000000000000..e70b8f22ee579ddb6994faf26b09f92777958520 --- /dev/null +++ b/fontes/dijkstra.h @@ -0,0 +1,22 @@ +vector<ll> d (N); vector<bool> vis (N); +vector<vector<int>> dag (N); +void dijkstra(int src, int dest) { + fill(d.begin(), d.end(), oo); + fill(vis.begin(), vis.end(), false); + priority_queue<ii, vector<ii>, greater<ii>> Q; + d[src] = 0; + Q.push({0, src}); + while (!Q.empty()) { + auto [c, u] = Q.top(); Q.pop(); + if (vis[u]) { continue; } + vis[u] = true; + for (auto [v, w] : gt[u]) if (d[u] == d[v] + w) + dag[v].push_back(u); + if (u == dest) { break; } + for (auto [v, w] : g[u]) + if (d[v] > d[u] + w) { + d[v] = d[u] + w; + Q.push({d[v], v}); + } + } +} diff --git a/fontes/diophantine.h b/fontes/diophantine.h new file mode 100644 index 0000000000000000000000000000000000000000..cf3818bf1a5e666db8c7b942df582fb45c744e05 --- /dev/null +++ b/fontes/diophantine.h @@ -0,0 +1,11 @@ +vector<ii> solve(ll a, ll b, ll c, int i) { + vector<ii> sol; + ll x, y, g = extgcd(a, b, x, y); + if (c % g) { return; } + x *= c/g; y *= c/g; + while (i--) { + sol.push_back(ii(x, y)); + x += b/g; y -= a/g; + } + return sol; +} diff --git a/fontes/disjoint.h b/fontes/disjoint.h new file mode 100644 index 0000000000000000000000000000000000000000..877e533aeb07b961286840f99bdaa59e3ef6ecee --- /dev/null +++ b/fontes/disjoint.h @@ -0,0 +1,21 @@ +vector<int> rep (N), rnk (N), siz (N); + +int ds_find(int u) { + if (rep[u] != u) { rep[u] = ds_find(rep[u]); } + return rep[u]; +} + +void ds_unite(int u, int v) { + u = ds_find(u); v = ds_find(v); + assert(u != v); + if (!(rnk[u] > rnk[v])) { swap(u, v); } + if (rnk[u] == rnk[v]) { rnk[u]++; } + rep[v] = u; + siz[u] += siz[v]; +} + +void ds_init(int n) { + for (int u = 0; u < n; u++) { + rep[u] = u; rnk[u] = 0; siz[u] = 1; + } +} diff --git a/fontes/euler-totient.cpp b/fontes/euler-totient.h similarity index 100% rename from fontes/euler-totient.cpp rename to fontes/euler-totient.h diff --git a/fontes/extended-gcd.cpp b/fontes/extended-gcd.cpp deleted file mode 100644 index 3da06f5c4ffc08a3fc436cc58abfe99912521e4b..0000000000000000000000000000000000000000 --- a/fontes/extended-gcd.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// ax + by = gcd(a, b) -// ax = gcd(a, b) (mod b) -// (gcd(a, b) = 1) => (ax = 1 (mod b)) -// -// Time: O(lg min(a, b)) -// Space: O(1) -struct gans { ll x, y, d; }; -gans ext_gcd(ll a, ll b) { - if (a == 0) return { 0, 1, b }; - gans e = ext_gcd(b % a, a); - return { e.y - (b/a)*e.x, e.x, e.d }; -} diff --git a/fontes/extgcd.h b/fontes/extgcd.h new file mode 100644 index 0000000000000000000000000000000000000000..7340bebf2a3618d5c675b8ff7e33660b54dfbe90 --- /dev/null +++ b/fontes/extgcd.h @@ -0,0 +1,11 @@ +ll extgcd(ll a, ll b, ll& x, ll& y) { + if (b == 0) { x = 1; y = 0; return a; } + ll g = extgcd(b, a%b, x, y); + tie(x, y) = make_tuple(y, x - (a/b)*y); + return g; +} + +ll inv(ll a, ll m) { + ll x, y; extgcd(a, m, x, y); + return ((x % m) + m) % m; +} diff --git a/fontes/factorize.cpp b/fontes/factorize.cpp deleted file mode 100644 index b76865e289d7fbc4e872d173705ceb8525495502..0000000000000000000000000000000000000000 --- a/fontes/factorize.cpp +++ /dev/null @@ -1,11 +0,0 @@ -void factorize(ll n) { - for (ll i = 2; i*i <= n; i++) { - while (n % i == 0) { - // process divisor - n /= i; - } - } - if (n > 1) { - // process n - } -} diff --git a/fontes/factorize.h b/fontes/factorize.h new file mode 100644 index 0000000000000000000000000000000000000000..1cf040c3dd97634b32f6b9ced3709f84ec197615 --- /dev/null +++ b/fontes/factorize.h @@ -0,0 +1,11 @@ +vector<int> factorize(ll n) { + vector<int> v; + for (ll i = 2; i*i <= n; i++) + while (n % i == 0) { + n /= i; + v.push_back(i); + } + if (n > 1) + v.push_back(n); + return v; +} diff --git a/fontes/fenwick-2d-tree.cpp b/fontes/fenwick-2d-tree.cpp deleted file mode 100644 index a2f401fd251835f35569000d109ab73bcc2afea5..0000000000000000000000000000000000000000 --- a/fontes/fenwick-2d-tree.cpp +++ /dev/null @@ -1,23 +0,0 @@ -vvi ftree(ftN, vi(ftM, 0)); // 1-indexed - -void ft_add /* O(lg^2 n) */ (int x,int y,int d) { - for (; x < ftN; x += x & -x) - for (int j = y; j < ftM; j += j & -j) - ftree[x][j] += d; -} - -int ft_rsq_upto /* O(lg^2 n) */ (int x, int y) { - int sum = 0; - for (; x > 0; x -= x & -x) - for (int j = y; j > 0; j -= j & -j) - sum += ftree[x][j]; - return sum; -} - -int ft_rsq /* O(lg^2 n) */ ( - int x1, int y1, int x2, int y2) { - return ft_rsq_upto(x2, y2) - - ft_rsq_upto(x2, y1 - 1) - - ft_rsq_upto(x1 - 1, y2) - + ft_rsq_upto(x1 - 1, y1 - 1); -} diff --git a/fontes/fenwick-2d-tree.h b/fontes/fenwick-2d-tree.h new file mode 100644 index 0000000000000000000000000000000000000000..044009d1548633d21fc50f78ad7fa5c983d3abdc --- /dev/null +++ b/fontes/fenwick-2d-tree.h @@ -0,0 +1,20 @@ +vector<vector<ll>> bit (N, vector<ll>(M)); + +void add(int x, int y, ll d) { + for (; x < N; x += x & -x) + for (int j = y; j < M; j += j & -j) + bit[x][j] += d; +} + +ll pref(int x, int y) { + ll sum = 0; + for (; x > 0; x -= x & -x) + for (int j = y; j > 0; j -= j & -j) + sum += bit[x][j]; + return sum; +} + +ll sum_inclusive(int x1, int y1, int x2, int y2) { + return pref(x2, y2) - pref(x2, y1 - 1) + - pref(x1 - 1, y2) + pref(x1 - 1, y1 - 1); +} diff --git a/fontes/fenwick-range-tree.cpp b/fontes/fenwick-range-tree.cpp deleted file mode 100644 index b9a0c753535dc161a91cddcd1567b90cb96ec079..0000000000000000000000000000000000000000 --- a/fontes/fenwick-range-tree.cpp +++ /dev/null @@ -1,20 +0,0 @@ -int ftN = 4*N; // O(n) -vi tree_a = vi(ftN, 0); // 1-indexed -vi tree_b = vi(ftN, 0); // 1-indexed - -// copy add and query - -int prefix_sum (int i) { - return query(tree_a, i) * i - query(tree_b, i); -} - -int range_sum (int i, int j) { - return prefix_sum(j) - prefix_sum(i - 1); -} - -void range_add (int a, int b, int d) { - add(tree_a, a, d); - add(tree_b, a, d * (a - 1)); - add(tree_a, b + 1, -d); - add(tree_b, b + 1, -d * b); -} diff --git a/fontes/fenwick-range-tree.h b/fontes/fenwick-range-tree.h new file mode 100644 index 0000000000000000000000000000000000000000..a8d6142c8b53cb41b81c80bc4f17f85e3993e588 --- /dev/null +++ b/fontes/fenwick-range-tree.h @@ -0,0 +1,26 @@ +vector<ll> bit1 (N), bit2 (N); + +void add(vector<ll>& bit, int i, ll d) { + for (; i < N; i += i & -i) { bit[i] += d; } +} + +ll pref(vector<ll>& bit, int i) { + ll sum = 0; + for (; i > 0; i -= i & -i) { sum += bit[i]; } + return sum; +} + +ll pref(int i) { + return pref(bit1, i) * i - pref(bit2, i); +} + +ll sum_inclusive(int i, int j) { + return pref(j) - pref(i - 1); +} + +void add_inclusive(int a, int b, ll d) { + add(bit1, a, d); + add(bit2, a, d * (a - 1)); + add(bit1, b + 1, -d); + add(bit2, b + 1, -d * b); +} diff --git a/fontes/fenwick-tree.cpp b/fontes/fenwick-tree.cpp deleted file mode 100644 index 58bbe39e40d2346e2fd28ed69791bf6d2d7312e8..0000000000000000000000000000000000000000 --- a/fontes/fenwick-tree.cpp +++ /dev/null @@ -1,25 +0,0 @@ -int ft_n = N; // O(n) -vi ftree(ft_n, 0); // 1-indexed - -void add /* O(lg n) */ (int i, int d) { - for (; i < ft_n; i += i & -i) - ftree[i] += d; -} - -int query /* O(lg n) */ (int i) { - int sum = 0; - for (; i > 0; i -= i & -i) - sum += ftree[i]; - return sum; -} - -// 1: add + range_sum, query is query_upto -int query_inclusive /* O(lg n) */ (int i, int j) { - return query(j) - query(i - 1); -} - -// 2: range_add + query, query is query -void add_inclusive (int a, int b, int d) { - add(a, d); - add(b + 1, -d); -} diff --git a/fontes/fenwick-tree.h b/fontes/fenwick-tree.h new file mode 100644 index 0000000000000000000000000000000000000000..bebaeef12e896ac8b45ce90238525e1ed12368ce --- /dev/null +++ b/fontes/fenwick-tree.h @@ -0,0 +1,20 @@ +vector<ll> bit (N, 0); + +void add(int i, ll d) { + for (; i < N; i += i & -i) { bit[i] += d; } +} + +ll pref(int i) { + int sum = 0; + for (; i > 0; i -= i & -i) { sum += bit[i]; } + return sum; +} + +int sum_inclusive(int i, int j) { + return pref(j) - pref(i - 1); +} + +void add_inclusive(int a, int b, ll d) { + add(a, d); + add(b + 1, -d); +} diff --git a/fontes/ffekbfs.h b/fontes/ffekbfs.h new file mode 100644 index 0000000000000000000000000000000000000000..56fcaa22ba0d06b68d9706b099399c8e1ddffa35 --- /dev/null +++ b/fontes/ffekbfs.h @@ -0,0 +1,18 @@ +vector<int> ix (N), dist (N), par (N); +bool minimum_path(int s, int t) { + fill(dist.begin(), dist.end(), oo); dist[s] = 0; + queue<int> q; q.push(s); + while (!q.empty()) { + int u = q.front(); q.pop(); + if (u == t) { break; } + for (int i : res[u]) { + edge e = edges[i]; int v = e.v; + if (e.cap && dist[v] == oo) { + dist[v] = dist[u] + 1; + par[v] = u; ix[v] = i; + q.push(v); + } + } + } + return dist[t] < oo; +} diff --git a/fontes/ffekspfa.h b/fontes/ffekspfa.h new file mode 100644 index 0000000000000000000000000000000000000000..1d6a97b4326042f8c88cdc8a76f5817dd192c827 --- /dev/null +++ b/fontes/ffekspfa.h @@ -0,0 +1,18 @@ +vector<int> queu (N), ix (N), dist (N), par (N); +bool minimum_path(int s, int t) { + fill(dist.begin(), dist.end(), oo); dist[s] = 0; + queue<int> q; q.push(s); + while (!q.empty()) { + int u = q.front(); q.pop(); + queu[u] = 0; + for (int i : res[u]) { + edge e = edges[i]; int v = e.v; + if (e.cap && dist[v] > dist[u] + e.cost) { + dist[v] = dist[u] + e.cost; + par[v] = u; ix[v] = i; + if (!queu[v]) { q.push(v); queu[v] = 1; } + } + } + } + return dist[t] < oo; +} diff --git a/fontes/floyd.h b/fontes/floyd.h new file mode 100644 index 0000000000000000000000000000000000000000..586099bfc2e6275a05da81ebd06af14ab2abeff8 --- /dev/null +++ b/fontes/floyd.h @@ -0,0 +1,14 @@ +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 }; +} diff --git a/fontes/floydhash.h b/fontes/floydhash.h new file mode 100644 index 0000000000000000000000000000000000000000..b0a3fade7b4eaf7ba16007efaddfa826dc0cc988 --- /dev/null +++ b/fontes/floydhash.h @@ -0,0 +1,16 @@ +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/geometry.cpp b/fontes/geometry.h similarity index 97% rename from fontes/geometry.cpp rename to fontes/geometry.h index 32f0a749583bff8c71125901406ac2406d9be9c8..5205be47cab64d9b6e3d100b1b7acdda518d7375 100644 --- a/fontes/geometry.cpp +++ b/fontes/geometry.h @@ -59,7 +59,7 @@ double distance_seg_seg(seg s, seg t) { return min({ v1, v2, v3, v4 }); } -bool is_inside_poly(vector<pt>& ps, pt p) { +bool is_inside_poly(vector<pt>& ps, pt p, bool strict) { int n = ps.size(); if (n < 3) { return false; } int count = 0; diff --git a/fontes/graham.h b/fontes/graham.h new file mode 100644 index 0000000000000000000000000000000000000000..5c488d128d77d10d5e72700ac748b8b6a3c5aeab --- /dev/null +++ b/fontes/graham.h @@ -0,0 +1,22 @@ +vector<pt> convex_hull(vector<pt>& ps, bool col = false) { + pt p0 = *min_element(ps.begin(), ps.end(), [](pt a, pt b) { + return make_pair(a.py, a.px) < make_pair(b.py, b.px); + }); + sort(ps.begin(), ps.end(), [&p0](pt a, pt b) { + int o = seg_ornt(p0, a, b); + return o < 0 || (o == 0 && norm(p0 - a) < norm(p0 - b)); + }); + if (col) { + int i = ps.size(); i--; + while (i >= 0 && seg_ornt(p0, ps[i], ps.back()) == 0) + i--; + reverse(ps.begin()+i+1, ps.end()); + } + vector<pt> ans; for (int i = 0; i < ps.size(); i++) { + while (ans.size() > 1 && !ccw( + ps[i], ans.back(), ans[ans.size()-2], col)) + ans.pop_back(); + ans.push_back(ps[i]); + } + return ans; +} diff --git a/fontes/grundy.cpp b/fontes/grundy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c6c092207e0dc140bdb298ca0b0f60526c614c3 --- /dev/null +++ b/fontes/grundy.cpp @@ -0,0 +1,21 @@ +#include <bits/stdc++.h> +using namespace std; +const int N = 1e6+15; +#include "mexset.h" +vector<int> g (N, -1); +int main() { + mex m (N); + for (int n = 0; n <= 1226; n++) { + if (n == 1 || n == 2) { g[n] = 0; continue; } + for (int i = 1; i <= n/2; i++) if (i != n-i) + m.insert_mex(g[i] ^ g[n-i]); + g[n] = m.get_reset_mex(); + } + int t; cin >> t; while (t--) { + int n; cin >> n; + if (n >= 1226) + cout << "first\n"; + else + cout << (g[n] != 0 ? "first" : "second") << "\n"; + } +} diff --git a/fontes/hash.sh b/fontes/hash.sh new file mode 100644 index 0000000000000000000000000000000000000000..15e11b440b04044a88cac789e33e6aadc6c8f693 --- /dev/null +++ b/fontes/hash.sh @@ -0,0 +1,3 @@ +# Hash das linhas [l1, l2] +sed -n $2','$3' p' $1 | sed '/^#w/d' | cpp -dD -P + -fpreprocessed | tr -d '[:space:]' | md5sum | cut -c-6 diff --git a/fontes/heavy-light-decomposition.cpp b/fontes/heavy-light-decomposition.cpp deleted file mode 100644 index a3a2fd2f1d42b3f43d10e26f0f33d106ec8f77f9..0000000000000000000000000000000000000000 --- a/fontes/heavy-light-decomposition.cpp +++ /dev/null @@ -1,51 +0,0 @@ -vi heavy(N, -1), anc(N, -1); -vi depth(N); - -int hld_fill /* O(V + E) */ (int u, int c) { - int w = 1, maxw = 0; - cost[u] = c; - for (auto v : graph[u]) { - if (v != anc[u]) { - anc[v] = u; - depth[v] = depth[u] + 1; - int cw = hld_fill(v); - w += cw; - if (cw > maxw) { - maxw = cw; - heavy[u] = v; - } - } - } - return w; -} - -vi hds(N), ixs(N); - -int cix = 1; - -void hld /* O(n lg n) */ (int u, int h = 1) { - hds[u] = h; - origin[cix] = cost[u]; - ixs[u] = cix++; - - if (heavy[u] != -1) - hld(heavy[u], h); // continue chain - - for (auto v : graph[u]) { - if (v != anc[u] && v != heavy[u]) - hld(v, v); // new chain - } -} - -ll hld_sum /* O(lg^2 n) */ (int u, int v) { - ll answer = 0; - for (; hds[u] != hds[v]; v = anc[hds[v]]) { - if (depth[hds[u]] > depth[hds[v]]) swap(u, v); - ll path_sum = query_inclusive(ixs[hds[v]], ixs[v]); - answer += path_sum; - } - if (depth[u] > depth[v]) swap(u, v); - - // Remove +1 if values are associated with vertices - return answer + query_inclusive(ixs[u] + 1, ixs[v]); -} diff --git a/fontes/hld.h b/fontes/hld.h new file mode 100644 index 0000000000000000000000000000000000000000..b9fe87274900b617fa724fdef0171bb01451354f --- /dev/null +++ b/fontes/hld.h @@ -0,0 +1,39 @@ +vector<int> hvy (N), par (N), dep (N), hds (N), ixs (N); +vector<ll> wei (N), ori (N); +int cix = 1; + +int hld_fill(int u, int p, int d = 0, ll w = 0) { + int s = 1, maxs = 0; + wei[u] = w; par[u] = p; dep[u] = d; hvy[u] = -1; + for (auto [v, w] : g[u]) if (v != p) { + int cs = hld_fill(v, u, d+1, w); + s += cs; + if (cs > maxs) { maxs = cs; hvy[u] = v; } + } + return s; +} + +void hld(int u, int h) { + hds[u] = h; + ori[cix] = wei[u]; + ixs[u] = cix++; + if (hvy[u] != -1) + hld(hvy[u], h); // continue chain + for (auto [v, w] : g[u]) if (v != par[u] && v != hvy[u]) + hld(v, v); // new chain +} + +ll hld_op(int u, int v, bool edge_wei = 1) { + ll ans = 0; + for (; hds[u] != hds[v]; v = par[hds[v]]) { + if (dep[hds[u]] > dep[hds[v]]) { swap(u, v); } + ans = OP(ans, + op_inclusive(ixs[hds[v]], ixs[v])); + } + if (dep[u] > dep[v]) { swap(u, v); } + return OP(ans, op_inclusive(ixs[u] + edge_wei, ixs[v])); +} + +void hld_init(int u) { + cix = 1; hld_fill(u, u); hld(u, u); build(ori); +} diff --git a/fontes/inclusion-exclusion.cpp b/fontes/inclusion-exclusion.h similarity index 100% rename from fontes/inclusion-exclusion.cpp rename to fontes/inclusion-exclusion.h diff --git a/fontes/interval-set.h b/fontes/interval-set.h new file mode 100644 index 0000000000000000000000000000000000000000..6368c3aac30bff72acd07da01a1a50b0988c2708 --- /dev/null +++ b/fontes/interval-set.h @@ -0,0 +1,38 @@ +struct itvl { + int a, b, c; + 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; + } +}; + +set<itvl, less<>>& si; + +void ins_in(itvl in) { + auto it = si.lower_bound(in); + int a = in.a, b = in.b, c = in.c; + if (si.size() > 0 && it != si.begin() + && prev(it)->b+1 == a && prev(it)->c == c) { + auto prv = prev(it); int prva = prv->a; + si.erase(prv); a = prva; + } + if (it != si.end() && c == it->c && b+1 == it->a) { + int nxtb = it->b; si.erase(it); b = nxtb; + } + si.insert(itvl(a, b, c)); +} + +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); + if (ori.a < a) { ins_in(itvl(ori.a, a-1, v)); } + if (ori.b > b) { ins_in(itvl(b+1, ori.b, v)); } + } + ins_in(itvl(a, b, c)); +} diff --git a/fontes/kd-tree.cpp b/fontes/kd-tree.cpp deleted file mode 100644 index 957d27b9e3b80bd6fc9ce5b68124aef701ecfdf8..0000000000000000000000000000000000000000 --- a/fontes/kd-tree.cpp +++ /dev/null @@ -1,78 +0,0 @@ -int get_ii(ii pair, int index) { - if (index == 0) { return pair.xx; } - else { return pair.yy; } -} - -class kdtree { - private: - struct node { - node(ii& p) : point(p), left(nullptr), right(nullptr) {} - double dist_sq(const ii& p) { - int dx = p.xx - point.xx; - int dy = p.yy - point.yy; - return dx*dx + dy*dy; - } - ii point; - node* left; - node* right; - }; - node* root = nullptr; - vector<double> best; - vector<node> nodes; - - struct node_cmp { - node_cmp(size_t _index) : index(_index) {} - bool operator()(const node& n1, const node& n2) { - return get_ii(n1.point, index) < get_ii(n2.point, index); - } - size_t index; - }; - - node* make_tree(size_t begin, size_t end, size_t index) { - if (end <= begin) - return nullptr; - size_t n = begin + (end - begin)/2; - nth_element(&nodes[begin], &nodes[n], &nodes[0] + end, node_cmp(index)); - index = (index + 1) % 2; - nodes[n].left = make_tree(begin, n, index); - nodes[n].right = make_tree(n + 1, end, index); - return &nodes[n]; - } - - void nearest_k(node* root, const ii& point, size_t index, int k) { - if (root == nullptr) - return; - double d = root->dist_sq(point); - if (best.size() < k || d < best[best.size()-1]) { - best.push_back(d); - sort(best.begin(), best.end()); - if (best.size() > k) { best.erase(best.begin() + k, best.end()); } - } - if (best.size() == 0) - return; - double dx = get_ii(root->point, index) - get_ii(point, index); - index = (index + 1) % 2; - nearest_k(dx > 0 ? root->left : root->right, point, index, k); - if (dx * dx >= best[best.size()-1]) - return; - nearest_k(dx > 0 ? root->right : root->left, point, index, k); - } - - public: - template<typename iterator> - kdtree(iterator begin, iterator end) : nodes(begin, end) { - root = make_tree(0, nodes.size(), 0); - } - - double nearest_k(const ii& pt, int k) { - if (root == nullptr) - throw logic_error("tree is empty"); - best.clear(); - nearest_k(root, pt, 0, k); - double acc = 0; - for (int i = 0; i < best.size(); i++) { - acc += sqrt(best[i]); - } - return acc; - } -}; diff --git a/fontes/kd-tree.h b/fontes/kd-tree.h new file mode 100644 index 0000000000000000000000000000000000000000..2e62a459117c5e9b1c17f063bdeccb106d8dd7cf --- /dev/null +++ b/fontes/kd-tree.h @@ -0,0 +1,73 @@ +int get_ii(pt pair, int ix) { + if (ix == 0) { return pair.px; } + else { return pair.py; } +} + +class kdtree { + private: + struct node { + node(pt& p) : p(p), left(nullptr), right(nullptr) {} + double dist_sq(const pt& o) { return norm(o - p); } + pt p; node* left, *right; + }; + node* root = nullptr; + vector<double> best; + vector<node> t; + + struct node_cmp { + node_cmp(size_t _index) : ix(_index) {} + bool operator()(const node& n1, const node& n2) { + return get_ii(n1.point, ix) < get_ii(n2.point, ix); + } + size_t ix; + }; + + node* make_tree(size_t begin, size_t end, size_t ix) { + if (end <= begin) + return nullptr; + size_t n = begin + (end - begin)/2; + nth_element(&t[begin], &t[n], &t[0] + end, node_cmp(ix)); + ix = (ix + 1) % 2; + t[n].left = make_tree(begin, n, ix); + t[n].right = make_tree(n + 1, end, ix); + return &t[n]; + } + + void nearest_k(node* r, const pt& p, size_t ix, int k) { + if (r == nullptr) + return; + double d = r->dist_sq(p); + if (best.size() < k || d < best[best.size()-1]) { + best.push_back(d); + sort(best.begin(), best.end()); + if (best.size() > k) + best.erase(best.begin() + k, best.end()); + } + if (best.size() == 0) + return; + double dx = get_ii(r->p, ix) - get_ii(p, ix); + ix = (ix + 1) % 2; + nearest_k(dx > 0 ? r->left : r->right, p, ix, k); + if (dx * dx >= best[best.size()-1]) + return; + nearest_k(dx > 0 ? r->right : r->left, p, ix, k); + } + + public: + template<typename iterator> + kdtree(iterator begin, iterator end) : t(begin, end) { + root = make_tree(0, t.size(), 0); + } + + double nearest_k(const pt& p, int k) { + if (root == nullptr) + throw logic_error("tree is empty"); + best.clear(); + nearest_k(root, p, 0, k); + double acc = 0; + for (int i = 0; i < best.size(); i++) { + acc += sqrt(best[i]); + } + return acc; + } +}; diff --git a/fontes/kmp.cpp b/fontes/kmp.cpp deleted file mode 100644 index 292b78460ae40c9c420473080bcbe8a2d3046df4..0000000000000000000000000000000000000000 --- a/fontes/kmp.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include <bits/stdc++.h> -using namespace std; - -// kmp_pre: O(m = |needle|) -vector<int> kmp_pre(string needle) { - vector<int> backtrack(needle.size()+1); - backtrack[0] = -1; - - int i = 0, j = -1; - while (i < needle.size()) { - while (j >= 0 && needle[i] != needle[j]) j = backtrack[j]; - i++; j++; - backtrack[i] = j; - } - - return backtrack; -} - -// kmp_search: O(n + m = |haystack| + |needle|) -// laço principal: O(n = |haystack|) -void kmp_search(string haystack, string needle) { - vector<int> backtrack = kmp_pre(needle); - - int i = 0, j = 0; - while (i < haystack.size()) { - while (j >= 0 && haystack[i] != needle[j]) j = backtrack[j]; - i++; j++; - if (j == needle.size()) { - // match at (i - j) - } - } -} - -int main() { - vector<int> t = kmp_pre("aabccaabccaabcc"); - for (auto x : t) { - cout << x << " "; - } - cout << "\n"; -} diff --git a/fontes/kmp.h b/fontes/kmp.h new file mode 100644 index 0000000000000000000000000000000000000000..e47fbce076a37dff55479d39be61893dcc48cfd5 --- /dev/null +++ b/fontes/kmp.h @@ -0,0 +1,25 @@ +vector<int> pre(string ne) { + int n = ne.size(); + vector<int> pi (n, 0); + for (int i = 1, j = 0; i < n; i++) { + while (j > 0 && ne[i] != ne[j]) { j = pi[j-1]; } + if (ne[i] == ne[j]) { j++; } + pi[i] = j; + } + return pi; +} + +int search(string hay, string ne) { + vector<int> pi = pre(ne); + int c = 0; + for (int i = 0, j = 0; i < hay.size(); i++) { + while (j > 0 && hay[i] != ne[j]) { j = pi[j-1]; } + if (hay[i] == ne[j]) { j++; } + if (j == ne.size()) { + c++; + // match at (i-j+1) + j = pi[j-1]; + } + } + return c; +} diff --git a/fontes/kruskal.cpp b/fontes/kruskal.cpp deleted file mode 100644 index 35299cff36b3eb9145d08d52206e4aeb9b772392..0000000000000000000000000000000000000000 --- a/fontes/kruskal.cpp +++ /dev/null @@ -1,40 +0,0 @@ -typedef pair<int, pair<int, int>> edge; -// edge -> e.cc, (e.uu.xx, e.uu.yy) - -vector<int> rep (n); -vector<int> rnk (n); -vector<int> siz (n, 1); -vector<edge> edges; - -int ds_find(int u) { - if (rep[u] != u) { rep[u] = ds_find(rep[u]); } - return rep[u]; -} - -void ds_union(int u, int v) { - u = ds_find(u); v = ds_find(v); - - assert(u != v); - if (!(rnk[u] > rnk[v])) { swap(u, v); } - if (rnk[u] == rnk[v]) { rnk[u]++; } - rep[v] = u; - siz[u] += siz[v]; -} - -int kruskal(int n) { - sort(edges.begin(), edges.end()); - for (int u = 1; u <= n; u++) { rep[u] = u; rnk[u] = 0; } - int components = n; - int total_cost = 0; - for (int i = 0; i < edges.size() && components > 1; i++) { - int u = e.uu.xx; - int v = e.uu.yy; - - if (ds_find(u) != ds_find(v)) { - ds_union(u, v); - components--; - total_cost += e.cc; - } - } - return components > 1 ? oo : total_cost; -} diff --git a/fontes/kruskal.h b/fontes/kruskal.h new file mode 100644 index 0000000000000000000000000000000000000000..37b3bb40846ead256c3a3c226cd6a63ab872d774 --- /dev/null +++ b/fontes/kruskal.h @@ -0,0 +1,20 @@ +struct edge { + int u, v, w; + bool operator<(struct edge &o) { return w < o.w; } +}; + +int kruskal(int n) { + sort(edges.begin(), edges.end()); + 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)) { + ds_union(u, v); + components--; + sum += w; + } + } + return sum; +} diff --git a/fontes/lazy-segment-tree.cpp b/fontes/lazy-segment-tree.cpp deleted file mode 100644 index dc0fd497224102fa8088c4f777fc8423273f2e70..0000000000000000000000000000000000000000 --- a/fontes/lazy-segment-tree.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#define LEFT 2*i -#define RIGH 2*i+1 - -struct node { - int data = 0; - - node() {}; - node(int x) { data = x; }; - - node operator+(const node& a) { - node n; n.data = a.data + data; return n; - }; - node operator+=(const int& a) { - data += a; return *this; - }; -}; - -const int N = 1e5+15; -const int LOG = ceil(log2(N)); - -struct dlta { int add = 0, set = -1; }; - -vector<ll> stree(2*N), origin(N); -vector<dlta> delta(2*N); - -ll apply(int i, dlta d, int sz) { - if (d.set != -1) { - stree[i] = d.set * sz; - delta[i] = { 0, d.set }; - } - if (d.add != 0) { - stree[i] += d.add * sz; - delta[i].add += d.add; - } - return stree[i]; -} - -void pull(int p) { - for (int s = __builtin_ctz(p)+1; s < LOG; s++) { - int i = p >> s; - stree[i] = stree[LEFT] + stree[RIGH]; - } -} - -void push(int p) { - int sz = 1 << (LOG-1); - for (int s = LOG; s > 0; s--, sz /= 2) { - int i = p >> s; - apply(LEFT, delta[i], sz); - apply(RIGH, delta[i], sz); - delta[i] = {}; - } -} - -ll op_range(int l, int r, char op = '\0', ll x = 0) { - dlta d; - if (op == '+') { d.add = x; } - if (op == '=') { d.set = x; } - int tl = l += N, tr = r += N, sz = 1; - push(tl); push(tr); - ll ans = 0; - for (; l < r; l /= 2, r /= 2, sz *= 2) { - if (l & 1) ans += apply(l++, d, sz); - if (r & 1) ans += apply(--r, d, sz); - } - pull(tl); pull(tr); - return ans; -} - -void build () { - for (int i = 0; i < N; i++) - stree[N+i] = origin[i]; - for (int i = N-1; i > 0; i--) - stree[i] = stree[LEFT] + stree[RIGH]; -} diff --git a/fontes/lstit.h b/fontes/lstit.h new file mode 100644 index 0000000000000000000000000000000000000000..02cb98989ad21fa717c765e217a85f0255f9122e --- /dev/null +++ b/fontes/lstit.h @@ -0,0 +1,71 @@ +const int L = ceil(log2(N)); +struct dlta { int add = 0, set = -1; }; +vector<ll> t (2*N); vector<dlta> delta (2*N); + +void build(vector<int>& src) { + for (int i = 1; i < src.size(); i++) + t[N+i] = src[i]; + for (int ti = N-1; ti > 0; ti--) + t[ti] = OP(t[2*ti], t[2*ti+1]); +} + +ll apply(int ti, dlta d, int sz) { + if (d.set != -1) { + t[ti] = ll(d.set) * FACTOR(sz); + delta[ti] = { 0, d.set }; + } + if (d.add != 0) { + t[ti] += ll(d.add) * FACTOR(sz); + delta[ti].add += d.add; + } + return t[ti]; +} + +void pull(int i) { + for (int s = __builtin_ctz(i)+1; s < L; s++) { + int ti = i >> s; + t[ti] = OP(t[2*ti], t[2*ti+1]); + } +} + +void push(int i) { + int sz = 1 << (L-1); + for (int s = L; s > 0; s--, sz /= 2) { + int ti = i >> s; + apply(2*ti, delta[ti], sz); + apply(2*ti+1, delta[ti], sz); + delta[ti] = {}; + } +} + +void apply_inclusive(int l, int r, + char op = '\0', ll x = 0) { + r++; + dlta d; + if (op == '+') { d.add = x; } + if (op == '=') { d.set = x; } + int tl = l += N, tr = r += N, sz = 1; + push(tl); push(tr); + for (; l < r; l /= 2, r /= 2, sz *= 2) { + if (l & 1) { apply(l++, d, sz); } + if (r & 1) { apply(--r, d, sz); } + } + pull(tl); pull(tr); +} + +void add_inclusive(int l, int r, ll d) { + apply_inclusive(l, r, '+', d); +} + +ll op_inclusive(int l, int r) { + r++; + int tl = l += N, tr = r += N, sz = 1; + push(tl); push(tr); + ll ans = NEUTRAL; + for (; l < r; l /= 2, r /= 2, sz *= 2) { + if (l & 1) ans = OP(ans, apply(l++, dlta(), sz)); + if (r & 1) ans = OP(ans, apply(--r, dlta(), sz)); + } + pull(tl); pull(tr); + return ans; +} diff --git a/fontes/lstrec.h b/fontes/lstrec.h new file mode 100644 index 0000000000000000000000000000000000000000..a586194ceea378aa615ef178357109a165a20d29 --- /dev/null +++ b/fontes/lstrec.h @@ -0,0 +1,61 @@ +vector<ll> t (4*N), lazy (4*N), sety (4*N, -1); + +void build(vector<int>& src, + int ti=1, int tl=1, int tr=N) { + if (tl == tr) { + if (tl < src.size()) { t[ti] = src[tl]; } + return; + } + int tm = (tl + tr) / 2; + build(src, ti*2, tl, tm); + build(src, ti*2+1, tm+1, tr); + t[ti] = OP(t[ti*2], t[ti*2+1]); +} + +void push(int ti, int tl, int tm, int tr) { + if (sety[ti] != -1) { + t[ti*2] = sety[ti] * FACTOR(tm - tl + 1); + lazy[ti*2] = 0; sety[ti*2] = sety[ti]; + t[ti*2+1] = sety[ti] * FACTOR(tr - (tm+1) + 1); + lazy[ti*2+1] = 0; sety[ti*2+1] = sety[ti]; + sety[ti] = -1; + } + t[ti*2] += lazy[ti] * FACTOR(tm - tl + 1); + lazy[ti*2] += lazy[ti]; + t[ti*2+1] += lazy[ti] * FACTOR(tr - (tm+1) + 1); + lazy[ti*2+1] += lazy[ti]; + 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, + 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); + lazy[ti] += d; 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); + t[ti] = OP(t[ti*2], t[ti*2+1]); +} + +ll op_inclusive(int l, int r, + int ti=1, int tl=1, int tr=N) { + if (l > r) { return NEUTRAL; } + if (l <= tl && tr <= r) { return t[ti]; } + int tm = (tl + tr) / 2; push(ti, tl, tm, tr); + return OP(op_inclusive(l, min(r, tm), ti*2, tl, tm), + op_inclusive(max(l, tm+1), r, ti*2+1, tm+1, tr)); +} diff --git a/fontes/merge-sort.cpp b/fontes/merge-sort.h similarity index 100% rename from fontes/merge-sort.cpp rename to fontes/merge-sort.h diff --git a/fontes/mex.cpp b/fontes/mex.cpp deleted file mode 100644 index 37a55370bd65aa99f30bffdf3eefc1bdcca8f8ee..0000000000000000000000000000000000000000 --- a/fontes/mex.cpp +++ /dev/null @@ -1,8 +0,0 @@ -int mex(set<int>& x) { - int m = 0; - for (auto &j : x) { - if (j > m) { return m; } - m++; - } - return m; -} diff --git a/fontes/mex.h b/fontes/mex.h new file mode 100644 index 0000000000000000000000000000000000000000..081bf295071f00fab7c7b0303841559c2f17b1f1 --- /dev/null +++ b/fontes/mex.h @@ -0,0 +1,10 @@ +struct mex { + vector<bool> tomex; int gt = 0; + mex(int n) : tomex(n) {}; + void insert_mex(int x) { tomex[x] = 1; gt = max(gt, x); } + int get_reset_mex() { + int m; for (m = 0; tomex[m]; m++); + fill(tomex.begin(), tomex.begin()+gt+1, 0); + return m; + } +}; diff --git a/fontes/mexset.h b/fontes/mexset.h new file mode 100644 index 0000000000000000000000000000000000000000..ca84990892fe97fdc0b2d1ac6437141a90ad2d06 --- /dev/null +++ b/fontes/mexset.h @@ -0,0 +1,11 @@ +struct mex { + set<int> tomex; + void insert_mex(int x) { tomex.insert(x); } + int get_reset_mex() { + int m = 0; for (auto &j : tomex) { + if (j > m) { tomex.clear(); return m; } + m++; + } + tomex.clear(); return m; + } +}; diff --git a/fontes/min-queue-2.cpp b/fontes/min-queue-2.h similarity index 100% rename from fontes/min-queue-2.cpp rename to fontes/min-queue-2.h diff --git a/fontes/min-queue-3.cpp b/fontes/min-queue-3.h similarity index 100% rename from fontes/min-queue-3.cpp rename to fontes/min-queue-3.h diff --git a/fontes/min-queue.cpp b/fontes/min-queue.h similarity index 100% rename from fontes/min-queue.cpp rename to fontes/min-queue.h diff --git a/fontes/min-stack.cpp b/fontes/min-stack.h similarity index 76% rename from fontes/min-stack.cpp rename to fontes/min-stack.h index 3dcae22fa39312b660e5a09b7a883bec7c087cb1..904b5c2ac3f551dd409f8afbdd2ea052c0798c1f 100644 --- a/fontes/min-stack.cpp +++ b/fontes/min-stack.h @@ -1,7 +1,7 @@ stack<pair<int, int>> st; void push_el(int x) { - int m = st.empty()?x:min(x, st.top().second); + int m = st.empty() ? x : min(x, st.top().second); st.push({x, m}); } int pop_el() { diff --git a/fontes/misere.cpp b/fontes/misere.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6298ac9f551a9ef7d938624315ae44a41cadb5b7 --- /dev/null +++ b/fontes/misere.cpp @@ -0,0 +1,18 @@ +#include <bits/stdc++.h> +using namespace std; +int main() { + cin.tie(0); + ios_base::sync_with_stdio(0); + int t; cin >> t; + while (t--) { + int n; cin >> n; + bool all_ones = true; + int res = 0; + for (int i = 0; i < n; i++) { + int x; cin >> x; res ^= x; + if (x != 1) { all_ones = false; } + } + if (all_ones) { res = n % 2 == 0; } + cout << (res != 0 ? "first" : "second") << "\n"; + } +} diff --git a/fontes/modular-multiplicative-inverse.cpp b/fontes/modular-multiplicative-inverse.cpp deleted file mode 100644 index fcfe8ad0747e02cc95e9ba59a04ec7265417722a..0000000000000000000000000000000000000000 --- a/fontes/modular-multiplicative-inverse.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// faster O(lg min(x, m)), arbitrary m (coprime), x^-1 (mod m) -int eucl_inv = (ext_gcd(x, m).x % m + m) % m; -// slower O(lg P), P is prime, x^-1 = x^(P-2) (mod P) -int fermat_inv = fast_pow(x, P - 2); diff --git a/fontes/monotone.h b/fontes/monotone.h new file mode 100644 index 0000000000000000000000000000000000000000..3e9769bdfa489f8379075685ef8af0bb96cd6f47 --- /dev/null +++ b/fontes/monotone.h @@ -0,0 +1,18 @@ +vector<pt> convex_hull(vector<pt>& ps, bool col = false) { + int k = 0, n = ps.size(); vector<pt> ans (2*n); + sort(ps.begin(), ps.end(), [](pt a, pt b) { + return make_pair(a.px, a.py) < make_pair(b.px, b.py); + }); + for (int i = 0; i < n; i++) { + while (k >= 2 && !ccw( /* lower hull */ + ans[k-2], ans[k-1], ps[i], col)) { k--; } + ans[k++] = ps[i]; + } + if (k == n) { ans.resize(n); return ans; } + for (int i = n-2, t = k+1; i >= 0; i--) { + while (k >= t && !ccw( /* upper hull */ + ans[k-2], ans[k-1], ps[i], col)) { k--; } + ans[k++] = ps[i]; + } + ans.resize(k-1); return ans; +} diff --git a/fontes/nge.cpp b/fontes/nge.cpp deleted file mode 100644 index e4bac6a7d309f208677836db658b599b0441bc59..0000000000000000000000000000000000000000 --- a/fontes/nge.cpp +++ /dev/null @@ -1,31 +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); -} - -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); -} - -stack<int> nge; -for (int i = 0; i < n; i++) { - while (!nge.empty() && v[nge.top()] < v[i]) { - ans[nge.top()] = i; nge.pop(); - } - nge.push(i); -} - -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/nge.h b/fontes/nge.h new file mode 100644 index 0000000000000000000000000000000000000000..f61e2aeb7a675927f278cf6a49681d8e4525c8f4 --- /dev/null +++ b/fontes/nge.h @@ -0,0 +1,7 @@ +stack<int> nge; +for (int i = 0; i < n; i++) { + while (!nge.empty() && v[nge.top()] < v[i]) { + ans[nge.top()] = i; nge.pop(); + } + nge.push(i); +} diff --git a/fontes/nim.cpp b/fontes/nim.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fa6f8bbe35ad400abc60579a8baeb847ac35fed1 --- /dev/null +++ b/fontes/nim.cpp @@ -0,0 +1,17 @@ +#include <bits/stdc++.h> +using namespace std; +int main() { + int n; while (cin >> n) { + int g = 0; + vector<int> s (n); + for (int i = 0; i < n; i++) { + cin >> s[i]; g ^= s[i]; } + if (g == 0) { cout << "-1\n"; continue; } + int msb = (1<<__lg(g)); + for (int i = 0; i < n; i++) if (s[i]&msb) { + int t = s[i]^g; + cout << s[i]-t << " " << i+1 << "\n"; + break; + } + } +} diff --git a/fontes/nk-first-digits.cpp b/fontes/nk-first-last-digits.h similarity index 55% rename from fontes/nk-first-digits.cpp rename to fontes/nk-first-last-digits.h index 7c3613474c18540668fd66c92d253b3f89487bc9..6070efb3b2bdf20cb692182a403bb84e00a3bd2a 100644 --- a/fontes/nk-first-digits.cpp +++ b/fontes/nk-first-last-digits.h @@ -3,3 +3,8 @@ int first_d_digits(int n, int k, int d) { logged -= int(logged) - (d-1); return int(pow(10, logged)); } + +int last_d_digits(int n, int k, int d) { + int p = 1; while (d--) { p *= 10; } + return fast_pow(n, k, p); +} diff --git a/fontes/nle.h b/fontes/nle.h new file mode 100644 index 0000000000000000000000000000000000000000..a2c886358e341a85fd71ac267f25768a415ff214 --- /dev/null +++ b/fontes/nle.h @@ -0,0 +1,7 @@ +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/node.h b/fontes/node.h new file mode 100644 index 0000000000000000000000000000000000000000..f0a514b51d46c86a869d830e6fb6ca7e4f4c05e4 --- /dev/null +++ b/fontes/node.h @@ -0,0 +1,9 @@ +struct node { + array<int, 9> data {{ 0 }}; + + node(); + explicit node(int x); + + node operator+(const node& a) { node n; return n; }; + node operator+=(const int& a) { return *this; }; +}; diff --git a/fontes/noncoprimecrt.cpp b/fontes/noncoprimecrt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ada3c3813001f80d52537185b86d3573bc30c7c --- /dev/null +++ b/fontes/noncoprimecrt.cpp @@ -0,0 +1,26 @@ +#include <bits/stdc++.h> +using namespace std; +using ll = long long; using vll = vector<ll>; +#include "extgcd.h" +ll norm(ll a, ll b) { a %= b; return (a < 0) ? a + b : a; } +pair<ll, ll> crt_single(ll a, ll n, ll b, ll m) { + ll x, y; ll g = extgcd(n, m, x, y); + if ((a - b) % g) { return {-1, -1}; } + ll lcm = (m/g) * n; + return {norm(a + n*(x*(b-a)/g % (m/g)), lcm), lcm}; +} +ll crt /* O(t lg m1*..*mt) */ (vll a, vll m, int t) { + ll ans = a[0], lcm = m[0]; + for (int i = 1; i < t; ++i) { + tie(ans, lcm) = crt_single(ans, lcm, a[i], m[i]); + if (ans == -1) { return -1; } + } + return ans; +} +int main() { + int t; while (cin >> t) { + vll a (t), m (t); + for (int i = 0; i < t; i++) { cin >> a[i] >> m[i]; } + cout << crt(a, m, t) << "\n"; + } +} diff --git a/fontes/numbers.cpp b/fontes/numbers.h similarity index 100% rename from fontes/numbers.cpp rename to fontes/numbers.h diff --git a/fontes/pascal-triangle.cpp b/fontes/pascal-triangle.h similarity index 100% rename from fontes/pascal-triangle.cpp rename to fontes/pascal-triangle.h diff --git a/fontes/pge.h b/fontes/pge.h new file mode 100644 index 0000000000000000000000000000000000000000..b9d1e97f2c324f5eb897d06764a64b9af98451e3 --- /dev/null +++ b/fontes/pge.h @@ -0,0 +1,7 @@ +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/ple.h b/fontes/ple.h new file mode 100644 index 0000000000000000000000000000000000000000..97985c2655f621495a5441cfcdf02d093089a9c8 --- /dev/null +++ b/fontes/ple.h @@ -0,0 +1,7 @@ +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/point.h b/fontes/point.h new file mode 100644 index 0000000000000000000000000000000000000000..822a380c0005b5d9c0fbe22559989377f623dc20 --- /dev/null +++ b/fontes/point.h @@ -0,0 +1,16 @@ +using pt = complex<double>; +#define px real() +#define py imag() +double dot(pt a, pt b) { return (conj(a) * b).px; } +double cross(pt a, pt b) { return (conj(a) * b).py; } +pt vec(pt a, pt b) { return b - a; } +int sgn(double v) { return (v > -EPS) - (v < EPS); } +// -1 (cw), 0 (colinear), +1 (ccw) +int seg_ornt(pt a, pt b, pt c) { + return sgn(cross(vec(a, b), vec(a, c))); } +int ccw(pt a, pt b, pt c, bool col) { + int o = seg_ornt(a, b, c); + return (o == 1) || (o == 0 && col); } +const double PI = acos(-1); +double angle(pt a, pt b, pt c) { + return abs(remainder(arg(a-b) - arg(c-b), 2.0 * PI)); } diff --git a/fontes/prefix-sum.cpp b/fontes/prefix-sum.cpp deleted file mode 100644 index 8d9132230eacd5915ad32ee68856d74c02c0b303..0000000000000000000000000000000000000000 --- a/fontes/prefix-sum.cpp +++ /dev/null @@ -1,11 +0,0 @@ -vector<ll> prefix_sum(N+1, 0); -vector<ll> origin(N); // origin has to be ll too - -void ps_build (int N) { - partial_sum(origin.begin(), origin.end(), prefix_sum.begin()+1); -} - -// [a, b) -ll ps_query (int a, int b) { - return prefix_sum[b] - prefix_sum[a]; -} diff --git a/fontes/prefix-sum.h b/fontes/prefix-sum.h new file mode 100644 index 0000000000000000000000000000000000000000..646f5144566cd520712eb409e1055f2785716ca3 --- /dev/null +++ b/fontes/prefix-sum.h @@ -0,0 +1,9 @@ +vector<ll> ps (N+1); + +void build(vector<ll>& origin) { + partial_sum(origin.begin(), origin.end(), ps.begin()+1); +} + +ll sum_inclusive(int a, int b) { + return ps[b+1] - ps[a]; +} diff --git a/fontes/prim.cpp b/fontes/prim.cpp deleted file mode 100644 index 395f9cf22e1d8afd55901577e204a2a265e32e95..0000000000000000000000000000000000000000 --- a/fontes/prim.cpp +++ /dev/null @@ -1,34 +0,0 @@ -vvii graph (N), prim_tree (N); -vector<bool> visited (N, false); -vi min_parent (N, -1), min_weight (N, oo); - -int prim (int initial) { - int weight_sum = 0; - priority_queue<ii, vii, greater<ii>> Q; - - Q.push(ii(0, initial)); - - while (!Q.empty()) { - int u = Q.top().uu; - int c = Q.top().cc; - Q.pop(); - - if (visited[u]) continue; visited[u] = true; - weight_sum += c; - - if (min_parent[u] != -1) { - int v = min_parent[u]; - int w = min_weight[u]; - prim_tree[u].push_back(ii(v, w)); - prim_tree[v].push_back(ii(u, w)); - } - - for (auto e : graph[u]) if (!visited[e.vv] && e.ww < min_weight[e.vv]) { - Q.push(ii(e.ww, e.vv)); - min_weight[e.vv] = e.ww; - min_parent[e.vv] = u; - } - } - - return weight_sum; -} diff --git a/fontes/prim.h b/fontes/prim.h new file mode 100644 index 0000000000000000000000000000000000000000..666a8f4ebce89e0176e7c23765d01b415d0209fe --- /dev/null +++ b/fontes/prim.h @@ -0,0 +1,26 @@ +vector<bool> vis (N); +vector<int> par (N, -1); +vector<ll> d (N, oo); +vector<vector<ii>> pt (N); +ll prim(int src) { + 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(); + if (vis[u]) { continue; } + vis[u] = true; + if (par[u] != -1) { + int v = par[u]; ll w = d[u]; + pt[u].push_back(ii(v, w)); + pt[v].push_back(ii(u, w)); + } + sum += c; + for (auto [v, w] : g[u]) + if (!vis[v] && w < d[v]) { + Q.push(ii(d[v] = w, v)); + par[v] = u; + } + } + return sum; +} diff --git a/fontes/rabinkarp.h b/fontes/rabinkarp.h new file mode 100644 index 0000000000000000000000000000000000000000..c725ee9349429ec2f71850775d66c04c2184af83 --- /dev/null +++ b/fontes/rabinkarp.h @@ -0,0 +1,20 @@ +const int P = 31; const int M = 1e9 + 9; +int search(string hay, string ne) { + int n = hay.size(), m = ne.size(); + vector<ll> ps (max(n, m), 1); + for (int i = 1; i < max(n, m); i++) + ps[i] = (ps[i-1] * P) % M; + vector<ll> h (n+1, 0); + for (int i = 0; i < n; i++) + h[i+1] = (h[i] + (hay[i]-'a'+1) * ps[i]) % M; + ll hne = 0; + for (int i = 0; i < m; i++) + hne = (hne + (ne[i]-'a'+1) * ps[i]) % M; + int c = 0; + for (int i = 0; i < n - m + 1; i++) + if ((h[i+m] - h[i] + M) % M == hne * ps[i] % M) { + // match at i + c++; + } + return c; +} diff --git a/fontes/segment-tree.cpp b/fontes/segment-tree.cpp deleted file mode 100644 index dabc300a9ad765e352b21c010354f472c1c7572b..0000000000000000000000000000000000000000 --- a/fontes/segment-tree.cpp +++ /dev/null @@ -1,37 +0,0 @@ -vector<T> stree(2*N), origin(N); - -#define LEFT 2*i -#define RIGH 2*i+1 -#define M (ta+tb)/2 - -void build /* O(n lg n) */ (int N) { - for (int i = 0; i < N; i++) - stree[N + i] = origin[i]; - for (int i = N - 1; i > 0; i--) - stree[i] = OP(stree[LEFT], stree[RIGH]); -} - -void update /* O(lg n) */ (int i, int d) { - stree[i += N] = d; - for (i /= 2; i > 0; i /= 2) - stree[i] = OP(stree[LEFT], stree[RIGH]); -} - -T query_exclusive /* O(lg n) */ (int i, int j) { - auto left = NEUTRAL, right = NEUTRAL; - for (i += N, j += N; i < j; i /= 2, j /= 2) { - if (i & 1) left = OP(left, stree[i++]); - if (j & 1) right = OP(right, stree[--j]); - } - return OP(left, right); -} - -struct node { - array<int, 9> data {{ 0 }}; - - node(); - explicit node(int x); - - node operator+(const node& a) { node n; return n; }; - node operator+=(const int& a) { return *this; }; -}; diff --git a/fontes/stupid-hash.cpp b/fontes/simple-hash.h similarity index 73% rename from fontes/stupid-hash.cpp rename to fontes/simple-hash.h index 652c6bd277b4c7b8d6bbbe3ae80194e170f65ae6..15a59aa893a7d8bb24c345a035146d553023b193 100644 --- a/fontes/stupid-hash.cpp +++ b/fontes/simple-hash.h @@ -1,21 +1,21 @@ const int HS = 10000; -vector<ll> key (HS), value (HS), ts (HS); - int cts = 0; +vector<ll> key (HS), value (HS), ts (HS); void hash_put(ll k, ll v) { ll pos = k % HS; - while (ts[pos] == cts) + while (ts[pos] == cts) { pos++; pos %= HS; + } ts[pos] = cts; - key[pos] = k; - value[pos] = v; + key[pos] = k; value[pos] = v; } ll hash_get(ll k) { ll pos = k % HS; - while (ts[pos] == cts && key[pos] != k) + while (ts[pos] == cts && key[pos] != k) { pos++; pos %= HS; + } if (ts[pos] == cts && key[pos] == k) return value[pos]; return -1; diff --git a/fontes/square-root-tree-decomposition.cpp b/fontes/square-root-tree-decomposition.cpp deleted file mode 100644 index 8b8fa9e2578bad7c6188cf6bd80c419ec85be5f8..0000000000000000000000000000000000000000 --- a/fontes/square-root-tree-decomposition.cpp +++ /dev/null @@ -1,44 +0,0 @@ -int B; - -vvil graph = vvil(MAX_N); - -vi heights (MAX_N); -vi parents (MAX_N); -vll costs (MAX_N); -vll upto_block_costs (MAX_N); -vi block_parents (MAX_N); - -void std_decompose (int u, int parent, int cost) { - parents[u] = parent; - costs[u] = cost; - - if (parent != -1) { - heights[u] = heights[parent] + 1; - block_parents[u] = heights[u] % B ? block_parents[parent] : parent; - upto_block_costs[u] = (heights[u] % B ? upto_block_costs[parent] : 0) + cost; - } - - for (auto e : graph[u]) { - int v, c; - tie(v, c) = e; - if (v != parent) { - std_decompose(v, u, c); - } - } -} - -ll std_query (int a, int b) { - ll result = 0; - - while (heights[a]/B > heights[b]/B) { result += upto_block_costs[a]; a = block_parents[a]; } - while (heights[b]/B > heights[a]/B) { result += upto_block_costs[b]; b = block_parents[b]; } - while (heights[a] > heights[b]) { result += costs[a]; a = parents[a]; } - while (heights[b] > heights[a]) { result += costs[b]; b = parents[b]; } - - while (a != b) { - result += costs[a]; a = parents[a]; - result += costs[b]; b = parents[b]; - } - - return result; -} diff --git a/fontes/stable-matching.cpp b/fontes/stable-matching.cpp deleted file mode 100644 index e71e6f581f97e57c7f4d4d1bbb60dabf3cc7d852..0000000000000000000000000000000000000000 --- a/fontes/stable-matching.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Gale-Shapley -// O(n^2) - -vector<vector<int>> pref_m (n, vector<int>(n)); // [m][j] = w -vector<vector<int>> pref_w_idx (n, vector<int>(n+1)); // [w][m] = j - -// m -vector<bool> single (n, true); -vector<int> match (n, -1); -// w -vector<int> watch (n, n); - -vector<ii> galeshapley(int n) { - // sentinel - for (int w = 0; w < n; w++) { pref_w_idx[w][n] = n; } - - bool done = false; - while (!done) { - done = true; - for (int m = 0; m < n; m++) if (single[m]) { - done = false; - match[m] += 1; - int w = pref_m[m][match[m]]; - if (pref_w_idx[w][m] < pref_w_idx[w][watch[w]]) { - single[watch[w]] = true; - watch[w] = m; - single[m] = false; - } - } - } - - vector<ii> ans; - for (int m = 0; m < n; m++) { - ans.push_back(ii(m, pref_m[m][match[m]])); - } - return ans; -} diff --git a/fontes/stable-matching.h b/fontes/stable-matching.h new file mode 100644 index 0000000000000000000000000000000000000000..eb2b5924a193d7fa5b7550eab899e3513ef756c4 --- /dev/null +++ b/fontes/stable-matching.h @@ -0,0 +1,30 @@ +vector<vector<int>> pm (N, vector<int>(N)); // [m][j] = w +vector<vector<int>> pwix (N, vector<int>(N+1)); // [w][m] = j + +vector<bool> single (N, true); +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 = false; + while (!done) { + done = true; + for (int m = 0; m < n; m++) if (single[m]) { + done = false; + match[m] += 1; + int w = pm[m][match[m]]; + if (pwix[w][m] < pwix[w][watch[w]]) { + single[watch[w]] = true; + watch[w] = m; + single[m] = false; + } + } + } + + vector<ii> ans; + for (int m = 0; m < n; m++) + ans.push_back(ii(m, pm[m][match[m]])); + return ans; +} diff --git a/fontes/stair.cpp b/fontes/stair.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ff33125cfe15916497281e1a0b46c32cf1442a2 --- /dev/null +++ b/fontes/stair.cpp @@ -0,0 +1,14 @@ +#include <bits/stdc++.h> +using namespace std; +int main() { + int t; cin >> t; + while (t--) { + int n; cin >> n; + int ans = 0; + for (int i = 0; i < n; i++) { + int p; cin >> p; + if (i % 2) { ans ^= p; } + } + cout << (ans == 0 ? "second" : "first") << "\n"; + } +} diff --git a/fontes/stdt.h b/fontes/stdt.h new file mode 100644 index 0000000000000000000000000000000000000000..fb51d9c81d66c3ea8fac7679f8b9e213765bba81 --- /dev/null +++ b/fontes/stdt.h @@ -0,0 +1,27 @@ +vector<int> depth (N); +vector<int> up (N); vector<int> weiop (N); +vector<int> bup (N); vector<int> bweiop (N); + +void stdt_decompose(int u, int p, int w) { + up[u] = p; weiop[u] = w; + depth[u] = depth[p] + 1; + bup[u] = depth[u] % B ? bup[p] : p; + bweiop[u] = OP(depth[u] % B ? bweiop[p] : NEUTRAL, w); + for (auto [v, w] : g[u]) if (v != p) + stdt_decompose(v, u, w); +} + +int stdt_op(int a, int b) { + int ans = NEUTRAL; + if (!(depth[a]/B > depth[b]/B)) { swap(a, b); } + while (depth[a]/B > depth[b]/B) { + ans = OP(ans, bweiop[a]); a = bup[a]; } + if (!(depth[a] > depth[b])) { swap(a, b); } + while (depth[a] > depth[b]) { + ans = OP(ans, weiop[a]); a = up[a]; } + while (a != b) { + ans = OP(ans, OP(weiop[a], weiop[b])); + a = up[a]; b = up[b]; + } + return ans; +} diff --git a/fontes/stdtlca.h b/fontes/stdtlca.h new file mode 100644 index 0000000000000000000000000000000000000000..41da9b4733c3612433535b3f284b0acc0476d7fb --- /dev/null +++ b/fontes/stdtlca.h @@ -0,0 +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; +} diff --git a/fontes/stdtop.h b/fontes/stdtop.h new file mode 100644 index 0000000000000000000000000000000000000000..71cfbf9ff1c420448f7bb3770facae58dec2d4da --- /dev/null +++ b/fontes/stdtop.h @@ -0,0 +1,14 @@ +int stdt_op(int a, int b) { + int ans = NEUTRAL; + if (!(depth[a]/B > depth[b]/B)) { swap(a, b); } + while (depth[a]/B > depth[b]/B) { + ans = OP(ans, bweiop[a]); a = bup[a]; } + if (!(depth[a] > depth[b])) { swap(a, b); } + while (depth[a] > depth[b]) { + ans = OP(ans, weiop[a]); a = up[a]; } + while (a != b) { + ans = OP(ans, OP(weiop[a], weiop[b])); + a = up[a]; b = up[b]; + } + return ans; +} diff --git a/fontes/stit.h b/fontes/stit.h new file mode 100644 index 0000000000000000000000000000000000000000..8ce8562d549e300372cc5b399c666da5bdb0b9a9 --- /dev/null +++ b/fontes/stit.h @@ -0,0 +1,24 @@ +vector<int> t (2*N); + +void build(vector<int>& src) { + for (int i = 1; i < src.size(); i++) + t[N+i] = src[i]; + for (int i = N-1; i > 0; i--) + t[i] = OP(t[2*i], t[2*i+1]); +} + +int op_inclusive(int l, int r) { + r++; + int left = NEUTRAL, right = NEUTRAL; + for (l += N, r += N; l < r; l /= 2, r /= 2) { + if (l & 1) left = OP(left, t[l++]); + if (r & 1) right = OP(right, t[--r]); + } + return OP(left, right); +} + +void set_value(int i, int v) { + t[i += N] = v; + for (i /= 2; i > 0; i /= 2) + t[i] = OP(t[i*2], t[i*2+1]); +} diff --git a/fontes/stoer-wagner.cpp b/fontes/stoer-wagner.h similarity index 100% rename from fontes/stoer-wagner.cpp rename to fontes/stoer-wagner.h diff --git a/fontes/strec.h b/fontes/strec.h new file mode 100644 index 0000000000000000000000000000000000000000..10916c2e8681ff14529e904752ff0d0320cde8c3 --- /dev/null +++ b/fontes/strec.h @@ -0,0 +1,33 @@ +vector<ll> t (4*N); + +void build(vector<ll>& src, + int ti=1, int tl=1, int tr=N) { + if (tl == tr) { + if (tl < src.size()) { t[ti] = src[tl]; } + return; + } + int tm = (tl + tr) / 2; + build(src, ti*2, tl, tm); + build(src, ti*2+1, tm+1, tr); + t[ti] = OP(t[ti*2], t[ti*2+1]); +} + +ll op_inclusive(int l, int r, + int ti=1, int tl=1, int tr=N) { + if (l > r) { return NEUTRAL; } + if (l == tl && r == tr) { return t[ti]; } + int tm = (tl + tr) / 2; + return OP(op_inclusive(l, min(r, tm), ti*2, tl, tm), + op_inclusive(max(l, tm+1), r, ti*2+1, tm+1, tr)); +} + +void set_value(int i, ll v, + int ti=1, int tl=1, int tr=N) { + if (tl == tr) { t[ti] = v; return; } + int tm = (tl + tr) / 2; + if (i <= tm) + set_value(i, v, ti*2, tl, tm); + else + set_value(i, v, ti*2+1, tm+1, tr); + t[ti] = OP(t[ti*2], t[ti*2+1]); +} diff --git a/fontes/suffix-tree.cpp b/fontes/suffix-tree.cpp deleted file mode 100644 index 33ab59b96bad754f766064628cde3d3f23faf19e..0000000000000000000000000000000000000000 --- a/fontes/suffix-tree.cpp +++ /dev/null @@ -1,73 +0,0 @@ -struct suffix_tree { - vector<vector<int>> nxt; - vector<int> l, r; - vector<int> parent; - vector<int> suf; - - suffix_tree() : nxt(MAXN, vector<int>(5)), l(MAXN), r(MAXN), - parent(MAXN), suf(MAXN) {} - - int len(int i) { return r[i] - l[i] + 1; } - - int at(string& s, int i, int j) { return id(s[l[i] + j]); } - - int cur = 1; - - int new_node (int a, int b, int p) { - l[cur] = a, r[cur] = b; - parent[cur] = p; - return cur++; - } - - void build (string s) { - s += '$'; - int root = new_node(0, -1, 0); - int u = root, i = 0, ui = 0, ns = 0; - for (int j = 0; j < s.size(); j++) - for (; i <= j; i++) { - if (ui == len(u) && nxt[u][id(s[j])]) { - u = nxt[u][id(s[j])]; - ui = 0; - } - if (ui < len(u) && at(s, u, ui) == id(s[j])) { - ui++; break; - } - if (ui == len(u)) { - nxt[u][id(s[j])] = new_node(j, s.size()-1, u); - if (u != root) { - u = suf[u]; - ui = len(u); - } - } else { - int mi = new_node(l[u], l[u] + ui - 1, parent[u]); - nxt[parent[u]][at(s, mi, 0)] = mi; - nxt[mi][at(s, u, ui)] = u; - parent[u] = mi; - l[u] += ui; - nxt[mi][id(s[j])] = new_node(j, s.size()-1, mi); - if (ns) { suf[ns] = mi; } - u = parent[mi]; - int g; - if (u != root) { - u = suf[u]; - g = j - ui; - } else { - g = i + 1; - } - while (g < j && g + len(nxt[u][id(s[g])]) <= j) { - u = nxt[u][id(s[g])]; - g += len(u); - } - if (g == j) { - ns = 0; - suf[mi] = u; - ui = len(u); - } else { - ns = mi; - u = nxt[u][id(s[g])]; - ui = j - g; - } - } - } - } -}; diff --git a/fontes/suffix-tree.h b/fontes/suffix-tree.h new file mode 100644 index 0000000000000000000000000000000000000000..fcfcbbe4677fa27d05db2cb47c35e8374c5dc415 --- /dev/null +++ b/fontes/suffix-tree.h @@ -0,0 +1,72 @@ +struct suffix_tree { + vector<vector<int>> nxt; + vector<int> l, r; + vector<int> parent; + vector<int> suf; + + suffix_tree() : nxt(N, vector<int>(5)), l(N), r(N), + parent(N), suf(N) {} + + int len(int i) { return r[i] - l[i] + 1; } + + int at(string& s, int i, int j) { return id(s[l[i] + j]); } + + int cur = 1; + + int new_node(int a, int b, int p) { + l[cur] = a, r[cur] = b; + parent[cur] = p; + return cur++; + } + + void build(string s) { + s += '$'; + int root = new_node(0, -1, 0); + int u = root, i = 0, ui = 0, ns = 0; + for (int j = 0; j < s.size(); j++) for (; i <= j; i++) { + if (ui == len(u) && nxt[u][id(s[j])]) { + u = nxt[u][id(s[j])]; + ui = 0; + } + if (ui < len(u) && at(s, u, ui) == id(s[j])) { + ui++; break; + } + if (ui == len(u)) { + nxt[u][id(s[j])] = new_node(j, s.size()-1, u); + if (u != root) { + u = suf[u]; + ui = len(u); + } + } else { + int mi = new_node(l[u], l[u] + ui - 1, parent[u]); + nxt[parent[u]][at(s, mi, 0)] = mi; + nxt[mi][at(s, u, ui)] = u; + parent[u] = mi; + l[u] += ui; + nxt[mi][id(s[j])] = new_node(j, s.size()-1, mi); + if (ns) { suf[ns] = mi; } + u = parent[mi]; + int g; + if (u != root) { + u = suf[u]; + g = j - ui; + } else { + g = i + 1; + } + while (g < j && g + len(nxt[u][id(s[g])]) <= j) { + u = nxt[u][id(s[g])]; + g += len(u); + } + if (g == j) { + ns = 0; + suf[mi] = u; + ui = len(u); + } else { + ns = mi; + u = nxt[u][id(s[g])]; + ui = j - g; + } + } + } + } +}; diff --git a/fontes/tarjan.h b/fontes/tarjan.h new file mode 100644 index 0000000000000000000000000000000000000000..8a16e74bc7087a7d65f650c7a0b8f6db6034eddb --- /dev/null +++ b/fontes/tarjan.h @@ -0,0 +1,20 @@ +vector<int> tin (N, -1), lowlnk (N, -1), rep (N); +stack<int> st; +void dfs_tarjan(int u) { + if (tin[u] != -1) { return; } + lowlnk[u] = tin[u] = vis[u] = cts++; + st.push(u); + for (int v : g[u]) { + dfs_tarjan(v); + if (vis[v]) lowlnk[u] = min(lowlnk[u], lowlnk[v]); + } + if (lowlnk[u] == tin[u]) { + int v; do { + v = st.top(); st.pop(); vis[v] = 0; + rep[v] = u; + } while (u != v); + } +} +void tarjan(int n) { + for (int u = 0; u < n; u++) { dfs_tarjan(u); } +} diff --git a/fontes/topo.h b/fontes/topo.h new file mode 100644 index 0000000000000000000000000000000000000000..e3b991201700a343716b01f280bd29d224ddca2b --- /dev/null +++ b/fontes/topo.h @@ -0,0 +1,17 @@ +vector<bool> vis (N); stack<int> st; +void dfs_topo(int u) { + if (vis[u]) { return; } + vis[u] = 1; + for (int v : g[u]) { dfs_topo(v); } + st.push(u); +} +vector<int> toposort(int n) { + fill(visited.begin(), visited.begin() + n, false); + vector<int> topo; + for (int u = 0; u < n; u++) { dfs_topo(u); } + while (!st.empty()) { + int v = st.top(); st.pop(); + topo.push_back(v); + } + return topo; +} diff --git a/fontes/topological-sort.cpp b/fontes/topological-sort.cpp deleted file mode 100644 index 0fd1a4d8189373b58f732bfa8e2e9b014e8772ba..0000000000000000000000000000000000000000 --- a/fontes/topological-sort.cpp +++ /dev/null @@ -1,17 +0,0 @@ -stack<int> S; -vector<bool> visited (n); - -void dfs(int u) { - if (visited[u]) return; - visited[u] = true; - for (int v : G[u]) { dfs(v); } - S.push(u); -} - -void topo_sort(int n) { - fill(visited.begin(), visited.begin() + n, false); - for (int u = 0; u < n; u++) { dfs(u); } - while (!S.empty()) { - int v = S.top(); S.pop(); - } -} diff --git a/fontes/trie.h b/fontes/trie.h new file mode 100644 index 0000000000000000000000000000000000000000..5fd31f9e27d3ca5fe4700f0c2880f6399e48fc9c --- /dev/null +++ b/fontes/trie.h @@ -0,0 +1,18 @@ +struct trie { + vector<int> nxt; int cnt; bool leaf; + trie() : nxt (S, -1), cnt (0), leaf (false) {} +}; +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 = true; +} diff --git a/testes/convex-hull.cpp b/testes/convex-hull.cpp deleted file mode 100644 index a3b322609163e0c1e11a18c697cd5f7e38fe10c3..0000000000000000000000000000000000000000 --- a/testes/convex-hull.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#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) x.begin(), x.end() -#define px real() -#define py imag() -#define mp make_pair -typedef complex<double> pt; -typedef vector<pt> vpt; - -int sgn (double v) { return (v > 0) - (v < 0); } -// -1 (cw), 0 (colinear), +1 (ccw) -int seg_ornt (pt a, pt b, pt c) { - return sgn(cross(vec(a, b), vec(a, c))); -} - -// doesn't include collinear points (<= -> < to include) -vpt convex_hull_ccw /* O(n lg n) */ (vpt& ps) { - int k = 0, n = ps.size(); - vpt result (n * 2); - - sort(all(ps), [](pt a, pt b) { - return mp(a.px, a.py) < mp(b.px, b.py); - }); - - for (int i = 0; i < n; i++) { - while (k >= 2 && seg_ornt( /* lower hull */ - result[k-2], result[k-1], ps[i]) <= 0) k--; - result[k++] = ps[i]; - } - - for (int i = n - 2, t = k + 1; i >= 0; i--) { - while (k >= t && seg_ornt( /* upper hull */ - result[k-2], result[k-1], ps[i]) <= 0) k--; - result[k++] = ps[i]; - } - - result.resize(k - 1); - return result; -} -vpt convex_hull_cw /* O(n lg n) */ (vpt& ps) { - int k = 0, n = ps.size(); - vpt result (n * 2); - - sort(all(ps), [](pt a, pt b) { - return mp(a.px, a.py) < mp(b.px, b.py); - }); - - for (int i = 0; i < n; i++) { - while (k >= 2 && seg_ornt( /* lower hull */ - result[k-2], result[k-1], ps[i]) >= 0) k--; - result[k++] = ps[i]; - } - - for (int i = n - 2, t = k + 1; i >= 0; i--) { - while (k >= t && seg_ornt( /* upper hull */ - result[k-2], result[k-1], ps[i]) >= 0) k--; - result[k++] = ps[i]; - } - - result.resize(k - 1); - return result; -} -vpt convex_hull_ccw_colinear /* O(n lg n) */ (vpt& ps) { - int k = 0, n = ps.size(); - vpt result (n * 2); - - sort(all(ps), [](pt a, pt b) { - return mp(a.px, a.py) < mp(b.px, b.py); - }); - - for (int i = 0; i < n; i++) { - while (k >= 2 && seg_ornt( /* lower hull */ - result[k-2], result[k-1], ps[i]) < 0) k--; - result[k++] = ps[i]; - } - - for (int i = n - 2, t = k + 1; i >= 0; i--) { - while (k >= t && seg_ornt( /* upper hull */ - result[k-2], result[k-1], ps[i]) < 0) k--; - result[k++] = ps[i]; - } - - result.resize(k - 1); - return result; -} - -vpt convex_hull_cw_colinear /* O(n lg n) */ (vpt& ps) { - int k = 0, n = ps.size(); - vpt result (n * 2); - - sort(all(ps), [](pt a, pt b) { - return mp(a.px, a.py) < mp(b.px, b.py); - }); - - for (int i = 0; i < n; i++) { - while (k >= 2 && seg_ornt( /* lower hull */ - result[k-2], result[k-1], ps[i]) > 0) k--; - result[k++] = ps[i]; - } - - for (int i = n - 2, t = k + 1; i >= 0; i--) { - while (k >= t && seg_ornt( /* upper hull */ - result[k-2], result[k-1], ps[i]) > 0) k--; - result[k++] = ps[i]; - } - - result.resize(k - 1); - return result; -} - -int main() { - ios::sync_with_stdio(0); cin.tie(0); - vpt convex; - - // 1 |* * - // 0 |* * * - // y +----- - // x 0 1 2 - vpt points { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 }, { 2, 1 } }; - - // 1 |3 2 - // 0 |0 * 1 - // y +----- - // x 0 1 2 - convex = convex_hull_ccw(points); - assert(convex.size() == 4); - assert(convex[0] == pt(0, 0)); - assert(convex[1] == pt(2, 0)); - assert(convex[2] == pt(2, 1)); - assert(convex[3] == pt(0, 1)); - - // 1 |1 2 - // 0 |0 * 3 - // y +----- - // x 0 1 2 - convex = convex_hull_cw(points); - assert(convex.size() == 4); - assert(convex[0] == pt(0, 0)); - assert(convex[1] == pt(0, 1)); - assert(convex[2] == pt(2, 1)); - assert(convex[3] == pt(2, 0)); - - // 1 |4 3 - // 0 |0 1 2 - // y +----- - // x 0 1 2 - convex = convex_hull_ccw_colinear(points); - assert(convex.size() == 5); - assert(convex[0] == pt(0, 0)); - assert(convex[1] == pt(1, 0)); - assert(convex[2] == pt(2, 0)); - assert(convex[3] == pt(2, 1)); - assert(convex[4] == pt(0, 1)); - - // 1 |1 2 - // 0 |0 4 3 - // y +----- - // x 0 1 2 - convex = convex_hull_cw_colinear(points); - assert(convex.size() == 5); - assert(convex[0] == pt(0, 0)); - assert(convex[1] == pt(0, 1)); - assert(convex[2] == pt(2, 1)); - assert(convex[3] == pt(2, 0)); - assert(convex[4] == pt(1, 0)); - - vpt ten_by_ten_grid; - - // 9 |* * * * * * * * * * - // 8 |* * * * * * * * * * - // 7 |* * * * * * * * * * - // 6 |* * * * * * * * * * - // 5 |* * * * * * * * * * - // 4 |* * * * * * * * * * - // 3 |* * * * * * * * * * - // 2 |* * * * * * * * * * - // 1 |* * * * * * * * * * - // 0 |* * * * * * * * * * - // y +------------------- - // x 0 1 2 3 4 5 6 7 8 9 - for (int i = 0; i < 100; i++) { - ten_by_ten_grid.push_back(pt(i / 10, i % 10)); - } - - // 9 |3 * * * * * * * * 2 - // 8 |* * * * * * * * * * - // 7 |* * * * * * * * * * - // 6 |* * * * * * * * * * - // 5 |* * * * * * * * * * - // 4 |* * * * * * * * * * - // 3 |* * * * * * * * * * - // 2 |* * * * * * * * * * - // 1 |* * * * * * * * * * - // 0 |0 * * * * * * * * 1 - // y +------------------- - // x 0 1 2 3 4 5 6 7 8 9 - convex = convex_hull_ccw(ten_by_ten_grid); - assert(convex.size() == 4); - assert(convex[0] == pt(0., 0.)); - assert(convex[1] == pt(9., 0.)); - assert(convex[2] == pt(9., 9.)); - assert(convex[3] == pt(0., 9.)); - - // 9 |1 * * * * * * * * 2 - // 8 |* * * * * * * * * * - // 7 |* * * * * * * * * * - // 6 |* * * * * * * * * * - // 5 |* * * * * * * * * * - // 4 |* * * * * * * * * * - // 3 |* * * * * * * * * * - // 2 |* * * * * * * * * * - // 1 |* * * * * * * * * * - // 0 |0 * * * * * * * * 3 - // y +------------------- - // x 0 1 2 3 4 5 6 7 8 9 - convex = convex_hull_cw(ten_by_ten_grid); - assert(convex.size() == 4); - assert(convex[0] == pt(0., 0.)); - assert(convex[1] == pt(0., 9.)); - assert(convex[2] == pt(9., 9.)); - assert(convex[3] == pt(9., 0.)); - - // 9 |R Q P O N M L K J I - // 8 |S * * * * * * * * H - // 7 |T * * * * * * * * G - // 6 |U * * * * * * * * F - // 5 |V * * * * * * * * E - // 4 |W * * * * * * * * D - // 3 |X * * * * * * * * C - // 2 |Y * * * * * * * * B - // 1 |Z * * * * * * * * A - // 0 |0 1 2 3 4 5 6 7 8 9 - // y +------------------- - // x 0 1 2 3 4 5 6 7 8 9 - convex = convex_hull_ccw_colinear(ten_by_ten_grid); - assert(convex.size() == 36); - for (int i = 0; i < 9; i++) assert(convex[i+9*0] == pt(i-0, 0.)); - for (int i = 0; i < 9; i++) assert(convex[i+9*1] == pt(9., i-0)); - for (int i = 0; i < 9; i++) assert(convex[i+9*2] == pt(9-i, 9.)); - for (int i = 0; i < 9; i++) assert(convex[i+9*3] == pt(0., 9-i)); - - // 9 |9 A B C D E F G H I - // 8 |8 * * * * * * * * J - // 7 |7 * * * * * * * * K - // 6 |6 * * * * * * * * L - // 5 |5 * * * * * * * * M - // 4 |4 * * * * * * * * N - // 3 |3 * * * * * * * * O - // 2 |2 * * * * * * * * P - // 1 |1 * * * * * * * * Q - // 0 |0 Z Y X W V U T S R - // y +------------------- - // x 0 1 2 3 4 5 6 7 8 9 - convex = convex_hull_cw_colinear(ten_by_ten_grid); - assert(convex.size() == 36); - for (int i = 0; i < 9; i++) assert(convex[i+9*0] == pt(0., i-0)); - for (int i = 0; i < 9; i++) assert(convex[i+9*1] == pt(i-0, 9.)); - for (int i = 0; i < 9; i++) assert(convex[i+9*2] == pt(9., 9-i)); - for (int i = 0; i < 9; i++) assert(convex[i+9*3] == pt(9-i, 0.)); -} diff --git a/testes/fenwick-2d-tree.cpp b/testes/fenwick-2d-tree.cpp index 8b3d46f4ed581648f3b529006f72a1e3cd559585..eaedb2fcc256e54882ed0a80b356254bf2733780 100644 --- a/testes/fenwick-2d-tree.cpp +++ b/testes/fenwick-2d-tree.cpp @@ -1,51 +1,23 @@ #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 << " ";} +const int N = 1e3 + 3; +const int M = 1e3 + 3; -const int ftN = 1e3 + 3; -const int ftM = 1e3 + 3; - -typedef vector<int> vi; -typedef vector<vector<int>> vvi; - -vvi ftree(ftN, vi(ftM, 0)); // 1-indexed - -void ft_add /* O(lg^2 n) */ (int x,int y,int d) { - for (; x < ftN; x += x & -x) - for (int j = y; j < ftM; j += j & -j) - ftree[x][j] += d; -} - -int ft_rsq_upto /* O(lg^2 n) */ (int x, int y) { - int sum = 0; - for (; x > 0; x -= x & -x) - for (int j = y; j > 0; j -= j & -j) - sum += ftree[x][j]; - return sum; -} - -int ft_rsq /* O(lg^2 n) */ ( - int x1, int y1, int x2, int y2) { - return ft_rsq_upto(x2, y2) - - ft_rsq_upto(x2, y1 - 1) - - ft_rsq_upto(x1 - 1, y2) - + ft_rsq_upto(x1 - 1, y1 - 1); -} +#include "../fontes/fenwick-2d-tree.h" int main() { ios::sync_with_stdio(0); cin.tie(0); - ft_add(1, 1, 1); - ft_add(1, 2, 3); - ft_add(1, 3, 9); - ft_add(2, 1, 5); - ft_add(2, 2, 5); - ft_add(2, 3, 8); - assert(ft_rsq(1, 1, 1, 1) == 1); - assert(ft_rsq(2, 2, 2, 2) == 5); - assert(ft_rsq(1, 1, 2, 2) == 1+3+5+5); - assert(ft_rsq(1, 1, 2, 3) == 1+3+9+5+5+8); + add(1, 1, 1); + add(1, 2, 3); + add(1, 3, 9); + add(2, 1, 5); + add(2, 2, 5); + add(2, 3, 8); + + assert(sum_inclusive(1, 1, 1, 1) == 1); + assert(sum_inclusive(2, 2, 2, 2) == 5); + assert(sum_inclusive(1, 1, 2, 2) == 1+3+5+5); + assert(sum_inclusive(1, 1, 2, 3) == 1+3+9+5+5+8); } diff --git a/testes/fenwick-2d-tree.gen b/testes/fenwick-2d-tree.gen deleted file mode 100755 index 78a4fe46051ff8bd2fbe2cae1b89ceed53aeb275..0000000000000000000000000000000000000000 --- a/testes/fenwick-2d-tree.gen +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -ed -s testes/fenwick-2d-tree.cpp <<'EOF' -# toggle debug helper -H -# delete all lines -,d -# add template -r fontes/template.cpp -# find main -/int main() {/ -# add info before main -i -const int ftN = 1e3 + 3; -const int ftM = 1e3 + 3; - -typedef vector<int> vi; -typedef vector<vector<int>> vvi; - -. -# add fenwick-2d-tree right before that space -.r fontes/fenwick-2d-tree.cpp -# add space after -a - -. -$i - ft_add(1, 1, 1); - ft_add(1, 2, 3); - ft_add(1, 3, 9); - ft_add(2, 1, 5); - ft_add(2, 2, 5); - ft_add(2, 3, 8); - - assert(ft_rsq(1, 1, 1, 1) == 1); - assert(ft_rsq(2, 2, 2, 2) == 5); - assert(ft_rsq(1, 1, 2, 2) == 1+3+5+5); - assert(ft_rsq(1, 1, 2, 3) == 1+3+9+5+5+8); -. -w -EOF diff --git a/testes/fenwick-tree.cpp b/testes/fenwick-tree.cpp index b7b9d9a00ab426bdc28153779eb789eb97ed8e63..57dc6be7e1650757cf9a0786b651ae579673b44e 100644 --- a/testes/fenwick-tree.cpp +++ b/testes/fenwick-tree.cpp @@ -1,42 +1,13 @@ #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 << " ";} +const int N = 1e5+15; -const int N = 1e5 + 3; - -typedef vector<int> vi; - -int ft_n = N; // O(n) -vi ftree(ft_n, 0); // 1-indexed - -void add /* O(lg n) */ (int i, int d) { - for (; i < ft_n; i += i & -i) - ftree[i] += d; -} - -int query /* O(lg n) */ (int i) { - int sum = 0; - for (; i > 0; i -= i & -i) - sum += ftree[i]; - return sum; -} - -// 1: add + range_sum, query is query_upto -int query_inclusive /* O(lg n) */ (int i, int j) { - return query(j) - query(i - 1); -} - -// 2: range_add + query, query is query -void add_inclusive (int a, int b, int d) { - add(a, d); - add(b + 1, -d); -} +#include "../fontes/fenwick-tree.h" int main() { ios::sync_with_stdio(0); cin.tie(0); + add(1, 1); add(2, 3); add(3, 5); @@ -47,16 +18,16 @@ int main() { add(8, 6); add(9, 2); - assert(range_query(1, 1) == 1); - assert(range_query(2, 2) == 3); - assert(range_query(3, 3) == 5); - assert(range_query(4, 4) == 6); - assert(range_query(5, 5) == 6); - assert(range_query(6, 6) == 9); - assert(range_query(7, 7) == 8); - assert(range_query(8, 8) == 6); - assert(range_query(9, 9) == 2); - assert(range_query(5, 8) == 6+9+8+6); - assert(range_query(1, 8) == 1+3+5+6+6+9+8+6); - assert(range_query(1, 9) == 1+3+5+6+6+9+8+6+2); + assert(sum_inclusive(1, 1) == 1); + assert(sum_inclusive(2, 2) == 3); + assert(sum_inclusive(3, 3) == 5); + assert(sum_inclusive(4, 4) == 6); + assert(sum_inclusive(5, 5) == 6); + assert(sum_inclusive(6, 6) == 9); + assert(sum_inclusive(7, 7) == 8); + assert(sum_inclusive(8, 8) == 6); + assert(sum_inclusive(9, 9) == 2); + assert(sum_inclusive(5, 8) == 6+9+8+6); + assert(sum_inclusive(1, 8) == 1+3+5+6+6+9+8+6); + assert(sum_inclusive(1, 9) == 1+3+5+6+6+9+8+6+2); } diff --git a/testes/fenwick-tree.gen b/testes/fenwick-tree.gen deleted file mode 100755 index 52356704bac1927192ef4c56fff9122c9945f70a..0000000000000000000000000000000000000000 --- a/testes/fenwick-tree.gen +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -ed -s testes/fenwick-tree.cpp <<'EOF' -# toggle debug helper -H -# delete all lines -,d -# add template -r fontes/template.cpp -# find main -/int main() {/ -# add info before main -i -const int N = 1e5 + 3; - -typedef vector<int> vi; - -. -# add fenwick-tree right before that space -.r fontes/fenwick-tree.cpp -# add space after -a - -. -$i - add(1, 1); - add(2, 3); - add(3, 5); - add(4, 6); - add(5, 6); - add(6, 9); - add(7, 8); - add(8, 6); - add(9, 2); - - assert(range_query(1, 1) == 1); - assert(range_query(2, 2) == 3); - assert(range_query(3, 3) == 5); - assert(range_query(4, 4) == 6); - assert(range_query(5, 5) == 6); - assert(range_query(6, 6) == 9); - assert(range_query(7, 7) == 8); - assert(range_query(8, 8) == 6); - assert(range_query(9, 9) == 2); - assert(range_query(5, 8) == 6+9+8+6); - assert(range_query(1, 8) == 1+3+5+6+6+9+8+6); - assert(range_query(1, 9) == 1+3+5+6+6+9+8+6+2); -. -w -EOF diff --git a/testes/hld-ps.cpp b/testes/hld-ps.cpp index 9dfc45a054ce7c0da1535fe01edfa034b63e19d2..e1f4bbf315b83860e14b6c6a4a862084505a493e 100644 --- a/testes/hld-ps.cpp +++ b/testes/hld-ps.cpp @@ -1,124 +1,40 @@ #include <bits/stdc++.h> -using namespace std; using ll = long long; +using namespace std; +using ll = long long; +using ii = pair<int, ll>; -#define $(X) {if (DEBUG) { \ - cerr << __LINE__ << ":"; {x} cerr << endl;}} -#define _(X) {cerr << #X << " = " << X << " ";} +const int N = 1e5+15; -const int N = 1e5 + 3; +vector<vector<ii>> g (N); -vector<ll> prefix_sum(N+1, 0); -vector<ll> origin(N); // origin has to be ll too - -void ps_build (int N) { - partial_sum(origin.begin(), origin.end(), prefix_sum.begin()+1); -} - -// [a, b) -ll ps_query (int a, int b) { - return prefix_sum[b] - prefix_sum[a]; -} - -ll ps_query_inclusive (int a, int b) { - return ps_query(a, b+1); -} - -typedef vector<ll> vi; -typedef pair<int, long> il; -typedef vector<vector<il>> vvil; - -vvil graph (N); -vi costs(N); -vi heavy(N, -1), anc(N, -1); -vi depth(N); - -int hld_fill /* O(V + E) */ (int u, int c) { - int w = 1, maxw = 0; - costs[u] = cost; - cost[u] = c; - for (auto e : graph[u]) { - int v, c; - tie(v, c) = e; - if (v != anc[u]) { - anc[v] = u; - depth[v] = depth[u] + 1; - int cw = hld_fill(v, c); - w += cw; - if (cw > maxw) { - maxw = cw; - heavy[u] = v; - } - } - } - return w; -} - -vi hds(N), ixs(N); - -int cix = 1; - -void hld /* O(n lg n) */ (int u, int h = 1) { - hds[u] = h; - origin[cix] = costs[u]; - origin[cix] = cost[u]; - ixs[u] = cix++; - - if (heavy[u] != -1) - hld(heavy[u], h); // continue chain - - for (auto e : graph[u]) { - int v, c; - tie(v, c) = e; - if (v != anc[u] && v != heavy[u]) - hld(v, v); // new chain - } -} - -ll hld_sum /* O(lg^2 n) */ (int u, int v) { - ll answer = 0; - for (; hds[u] != hds[v]; v = anc[hds[v]]) { - if (depth[hds[u]] > depth[hds[v]]) swap(u, v); - ll path_sum = query_inclusive(ixs[hds[v]], ixs[v]); - answer += path_sum; - } - if (depth[u] > depth[v]) swap(u, v); - - // Remove +1 if values are associated with vertices - return answer + query_inclusive(ixs[u] + 1, ixs[v]); -} +#define OP(X, Y) ((X) + (Y)) +#include "../fontes/prefix-sum.h" +#define op_inclusive sum_inclusive +#include "../fontes/hld.h" int main() { ios::sync_with_stdio(0); cin.tie(0); - int N; - while (cin >> N, N != 0) { - for (int i = 0; i < N+1; i++) - graph[i].clear(); + int n; + while (cin >> n && n) { + for (int u = 0; u < n; u++) + g[u].clear(); - fill(parents.begin(), parents.end(), -1); - fill(heavy.begin(), heavy.end(), -1); - - for (int a = 1; a <= N - 1; a++) { - int b, t; - cin >> b >> t; - graph[a].push_back(il(b, t)); - graph[b].push_back(il(a, t)); + for (int a = 1; a < n; a++) { + int b, t; cin >> b >> t; + g[a].push_back(ii(b, t)); + g[b].push_back(ii(a, t)); } - cix = 1; - - hld_fill(1, 0); - hld(1, 1); - ps_build(cix); - - int Q; - cin >> Q; + hld_init(0); - for (int i = 0; i < Q; i++) { - int a, b; - cin >> a >> b; - if (i != 0) cout << " "; - cout << hld_sum(a, b); + bool first = true; + int q; cin >> q; + while (q--) { + int a, b; cin >> a >> b; + if (!first) cout << " "; + first = false; + cout << hld_op(a, b); } cout << "\n"; diff --git a/testes/hld-ps.gen b/testes/hld-ps.gen deleted file mode 100755 index 6cdaf50706a6ccddac65a4a0659849f3966d2b7a..0000000000000000000000000000000000000000 --- a/testes/hld-ps.gen +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/sh -ed -s testes/hld-ps.cpp <<'EOF' -# toggle debug helper -H -# delete all lines -,d -# add template -r fontes/template.cpp -# find main -/int main() {/ -# add info before main -i -const int N = 1e5 + 3; - -. -# add prefix-sum right before that space -.r fontes/prefix-sum.cpp -# add space after -a - -ll ps_query_inclusive (int a, int b) { - return ps_query(a, b+1); -} - -. -# add content before -i - -typedef vector<ll> vi; -typedef pair<int, long> il; -typedef vector<vector<il>> vvil; - -vvil graph (N); -vi costs(N); -. -# add heavy-light-decomposition after -.r fontes/heavy-light-decomposition.cpp -# patch hld_fill with cost -,s/hld_fill \(.\+\) (int u)/hld_fill \1 (int u, int cost)/ -# find maxw line -/maxw/ -# add costs patch after -a - costs[u] = cost; -. -# patch for from hld_fill -.,+2s/for (auto v : graph\[u\])/for (auto e : graph[u])/ -a - int v, c; - tie(v, c) = e; -. -# patch hld_fill function call -.,+5s/hld_fill(v)/hld_fill(v, c)/ -# patch for from hld -/void hld / -/hds/ -a - origin[cix] = costs[u]; -. -/void hld / -.,+9s/for (auto v : graph\[u\])/for (auto e : graph[u])/ -a - int v, c; - tie(v, c) = e; -. -# patch hld_query -/ll hld_sum / -.,+12s/query(/ps_query_inclusive(/ -$i - - int N; - while (cin >> N, N != 0) { - for (int i = 0; i < N+1; i++) - graph[i].clear(); - - fill(parents.begin(), parents.end(), -1); - fill(heavy.begin(), heavy.end(), -1); - - for (int a = 1; a <= N - 1; a++) { - int b, t; - cin >> b >> t; - graph[a].push_back(il(b, t)); - graph[b].push_back(il(a, t)); - } - - cix = 1; - - hld_fill(1, 0); - hld(1, 1); - ps_build(cix); - - int Q; - cin >> Q; - - for (int i = 0; i < Q; i++) { - int a, b; - cin >> a >> b; - if (i != 0) cout << " "; - cout << hld_sum(a, b); - } - - cout << "\n"; - } -. -w -EOF diff --git a/testes/lazy-segment-tree.cpp b/testes/lazy-segment-tree.cpp deleted file mode 100644 index b57d05ec004024b2692444ccbb56fb35e845a16e..0000000000000000000000000000000000000000 --- a/testes/lazy-segment-tree.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#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 OP(X, Y) (X + Y) -#define NEUTRAL 0 -#define FACTOR (tb - ta + 1) - -const int N = 1e5 + 3; - -#define LEFT 2*i -#define RIGH 2*i+1 - -struct node { - int data = 0; - - node() {}; - node(int x) { data = x; }; - - node operator+(const node& a) { - node n; n.data = a.data + data; return n; - }; - node operator+=(const int& a) { - data += a; return *this; - }; -}; - -const int N = 1e5+15; -const int LOG = ceil(log2(N)); - -struct dlta { int add = 0, set = -1; }; - -vector<ll> stree(2*N), origin(N); -vector<dlta> delta(2*N); - -ll apply(int i, dlta d, int sz) { - if (d.set != -1) { - stree[i] = d.set * sz; - delta[i] = { 0, d.set }; - } - if (d.add != 0) { - stree[i] += d.add * sz; - delta[i].add += d.add; - } - return stree[i]; -} - -void pull(int p) { - for (int s = __builtin_ctz(p)+1; s < LOG; s++) { - int i = p >> s; - stree[i] = stree[LEFT] + stree[RIGH]; - } -} - -void push(int p) { - int sz = 1 << (LOG-1); - for (int s = LOG; s > 0; s--, sz /= 2) { - int i = p >> s; - apply(LEFT, delta[i], sz); - apply(RIGH, delta[i], sz); - delta[i] = {}; - } -} - -ll op_range(int l, int r, char op = '\0', ll x = 0) { - dlta d; - if (op == '+') { d.add = x; } - if (op == '=') { d.set = x; } - int tl = l += N, tr = r += N, sz = 1; - push(tl); push(tr); - ll ans = 0; - for (; l < r; l /= 2, r /= 2, sz *= 2) { - if (l & 1) ans += apply(l++, d, sz); - if (r & 1) ans += apply(--r, d, sz); - } - pull(tl); pull(tr); - return ans; -} - -void build () { - for (int i = 0; i < N; i++) - stree[N+i] = origin[i]; - for (int i = N-1; i > 0; i--) - stree[i] = stree[LEFT] + stree[RIGH]; -} -int main() { - ios::sync_with_stdio(0); cin.tie(0); - op_range(1, 10, '+', 1); - op_range(1, 8, '+', 1); - op_range(2, 4, '+', 5); - op_range(3, 8, '+', 3); - - op_range(1, 10, '=', 0); - - assert(op_range(1, 1).data == 0); - assert(op_range(2, 2).data == 0); - assert(op_range(3, 3).data == 0); - assert(op_range(4, 4).data == 0); - assert(op_range(5, 5).data == 0); - assert(op_range(6, 6).data == 0); - assert(op_range(7, 7).data == 0); - assert(op_range(8, 8).data == 0); - assert(op_range(9, 9).data == 0); - - assert(op_range(5, 8).data == 0); - assert(op_range(1, 8).data == 0); - assert(op_range(1, 9).data == 0); - - op_range(1, 10, '+', 1); - op_range(1, 8, '+', 1); - op_range(2, 4, '+', 5); - op_range(3, 8, '+', 3); - - assert(op_range(1, 1).data == 2); - assert(op_range(2, 2).data == 7); - assert(op_range(3, 3).data == 10); - assert(op_range(4, 4).data == 10); - assert(op_range(5, 5).data == 5); - assert(op_range(6, 6).data == 5); - assert(op_range(7, 7).data == 5); - assert(op_range(8, 8).data == 5); - assert(op_range(9, 9).data == 1); - - assert(op_range(5, 8).data == 20); - assert(op_range(1, 8).data == 49); - assert(op_range(1, 9).data == 50); - - op_range(1, 10, '+', 1); - - assert(op_range(1, 1).data == 3); - assert(op_range(2, 2).data == 8); - assert(op_range(3, 3).data == 11); - assert(op_range(4, 4).data == 11); - assert(op_range(5, 5).data == 6); - assert(op_range(6, 6).data == 6); - assert(op_range(7, 7).data == 6); - assert(op_range(8, 8).data == 6); - assert(op_range(9, 9).data == 2); - - assert(op_range(5, 8).data == 24); - assert(op_range(1, 8).data == 57); - assert(op_range(1, 9).data == 59); - - op_range(1, 7, '=', 0); - - assert(op_range(1, 1).data == 0); - assert(op_range(2, 2).data == 0); - assert(op_range(3, 3).data == 0); - assert(op_range(4, 4).data == 0); - assert(op_range(5, 5).data == 0); - assert(op_range(6, 6).data == 0); - assert(op_range(7, 7).data == 0); - assert(op_range(8, 8).data == 6); - assert(op_range(9, 9).data == 2); - - assert(op_range(5, 7).data == 0); - assert(op_range(5, 8).data == 6); - assert(op_range(1, 8).data == 6); - assert(op_range(1, 9).data == 8); -} diff --git a/testes/lazy-segment-tree.gen b/testes/lazy-segment-tree.gen deleted file mode 100755 index 38d6cf05573941d2c88bf852ff726062863a6537..0000000000000000000000000000000000000000 --- a/testes/lazy-segment-tree.gen +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/sh -ed -s testes/lazy-segment-tree.cpp <<'EOF' -# toggle debug helper -H -# -# delete all lines -,d -# -# add template -r fontes/template.cpp -# -# find main -/int main() {/ -# -# add info before main -i -#define OP(X, Y) (X + Y) -#define NEUTRAL 0 -#define FACTOR (tb - ta + 1) - -const int N = 1e5 + 3; - -. -# -# add fenwick-tree right before that space -.r fontes/lazy-segment-tree.cpp -$i - op_range(1, 10, '+', 1); - op_range(1, 8, '+', 1); - op_range(2, 4, '+', 5); - op_range(3, 8, '+', 3); - - op_range(1, 10, '=', 0); - - assert(op_range(1, 1).data == 0); - assert(op_range(2, 2).data == 0); - assert(op_range(3, 3).data == 0); - assert(op_range(4, 4).data == 0); - assert(op_range(5, 5).data == 0); - assert(op_range(6, 6).data == 0); - assert(op_range(7, 7).data == 0); - assert(op_range(8, 8).data == 0); - assert(op_range(9, 9).data == 0); - - assert(op_range(5, 8).data == 0); - assert(op_range(1, 8).data == 0); - assert(op_range(1, 9).data == 0); - - op_range(1, 10, '+', 1); - op_range(1, 8, '+', 1); - op_range(2, 4, '+', 5); - op_range(3, 8, '+', 3); - - assert(op_range(1, 1).data == 2); - assert(op_range(2, 2).data == 7); - assert(op_range(3, 3).data == 10); - assert(op_range(4, 4).data == 10); - assert(op_range(5, 5).data == 5); - assert(op_range(6, 6).data == 5); - assert(op_range(7, 7).data == 5); - assert(op_range(8, 8).data == 5); - assert(op_range(9, 9).data == 1); - - assert(op_range(5, 8).data == 20); - assert(op_range(1, 8).data == 49); - assert(op_range(1, 9).data == 50); - - op_range(1, 10, '+', 1); - - assert(op_range(1, 1).data == 3); - assert(op_range(2, 2).data == 8); - assert(op_range(3, 3).data == 11); - assert(op_range(4, 4).data == 11); - assert(op_range(5, 5).data == 6); - assert(op_range(6, 6).data == 6); - assert(op_range(7, 7).data == 6); - assert(op_range(8, 8).data == 6); - assert(op_range(9, 9).data == 2); - - assert(op_range(5, 8).data == 24); - assert(op_range(1, 8).data == 57); - assert(op_range(1, 9).data == 59); - - op_range(1, 7, '=', 0); - - assert(op_range(1, 1).data == 0); - assert(op_range(2, 2).data == 0); - assert(op_range(3, 3).data == 0); - assert(op_range(4, 4).data == 0); - assert(op_range(5, 5).data == 0); - assert(op_range(6, 6).data == 0); - assert(op_range(7, 7).data == 0); - assert(op_range(8, 8).data == 6); - assert(op_range(9, 9).data == 2); - - assert(op_range(5, 7).data == 0); - assert(op_range(5, 8).data == 6); - assert(op_range(1, 8).data == 6); - assert(op_range(1, 9).data == 8); -. -w -EOF diff --git a/testes/lstit.cpp b/testes/lstit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ccf0cebbcaf9d7cdfe070f497df09296ab7da40e --- /dev/null +++ b/testes/lstit.cpp @@ -0,0 +1,85 @@ +#include <bits/stdc++.h> +using namespace std; +using ll = long long; +const int N = 1e5+15; +#define OP(X, Y) ((X) + (Y)) +#define NEUTRAL 0 +#define FACTOR(sz) sz +#include "../fontes/lstit.h" + +int main() { + ios::sync_with_stdio(0); cin.tie(0); + + apply_inclusive(1, 10, '+', 1); + apply_inclusive(1, 8, '+', 1); + apply_inclusive(2, 4, '+', 5); + apply_inclusive(3, 8, '+', 3); + + apply_inclusive(1, 10, '=', 0); + + assert(op_inclusive(1, 1) == 0); + assert(op_inclusive(2, 2) == 0); + assert(op_inclusive(3, 3) == 0); + assert(op_inclusive(4, 4) == 0); + assert(op_inclusive(5, 5) == 0); + assert(op_inclusive(6, 6) == 0); + assert(op_inclusive(7, 7) == 0); + assert(op_inclusive(8, 8) == 0); + assert(op_inclusive(9, 9) == 0); + + assert(op_inclusive(5, 8) == 0); + assert(op_inclusive(1, 8) == 0); + assert(op_inclusive(1, 9) == 0); + + apply_inclusive(1, 10, '+', 1); + apply_inclusive(1, 8, '+', 1); + apply_inclusive(2, 4, '+', 5); + apply_inclusive(3, 8, '+', 3); + + assert(op_inclusive(1, 1) == 2); + assert(op_inclusive(2, 2) == 7); + assert(op_inclusive(3, 3) == 10); + assert(op_inclusive(4, 4) == 10); + assert(op_inclusive(5, 5) == 5); + assert(op_inclusive(6, 6) == 5); + assert(op_inclusive(7, 7) == 5); + assert(op_inclusive(8, 8) == 5); + assert(op_inclusive(9, 9) == 1); + + assert(op_inclusive(5, 8) == 20); + assert(op_inclusive(1, 8) == 49); + assert(op_inclusive(1, 9) == 50); + + apply_inclusive(1, 10, '+', 1); + + assert(op_inclusive(1, 1) == 3); + assert(op_inclusive(2, 2) == 8); + assert(op_inclusive(3, 3) == 11); + assert(op_inclusive(4, 4) == 11); + assert(op_inclusive(5, 5) == 6); + assert(op_inclusive(6, 6) == 6); + assert(op_inclusive(7, 7) == 6); + assert(op_inclusive(8, 8) == 6); + assert(op_inclusive(9, 9) == 2); + + assert(op_inclusive(5, 8) == 24); + assert(op_inclusive(1, 8) == 57); + assert(op_inclusive(1, 9) == 59); + + apply_inclusive(1, 7, '=', 0); + + assert(op_inclusive(1, 1) == 0); + assert(op_inclusive(2, 2) == 0); + assert(op_inclusive(3, 3) == 0); + assert(op_inclusive(4, 4) == 0); + assert(op_inclusive(5, 5) == 0); + assert(op_inclusive(6, 6) == 0); + assert(op_inclusive(7, 7) == 0); + assert(op_inclusive(8, 8) == 6); + assert(op_inclusive(9, 9) == 2); + + assert(op_inclusive(5, 7) == 0); + assert(op_inclusive(5, 8) == 6); + assert(op_inclusive(1, 8) == 6); + assert(op_inclusive(1, 9) == 8); +} diff --git a/testes/convex-hull.gen b/testes/monotone.cpp old mode 100755 new mode 100644 similarity index 54% rename from testes/convex-hull.gen rename to testes/monotone.cpp index 4677e3fc9c747d6987faa805d77bc0cee4fa0c7e..2c4e22247ec44a3708f298058a5b465532f4abda --- a/testes/convex-hull.gen +++ b/testes/monotone.cpp @@ -1,72 +1,25 @@ -#!/bin/sh -ed -s testes/convex-hull.cpp <<'EOF' -# toggle debug helper -H -w -# delete all lines -,d -# add template -r fontes/template.cpp -# find main -/int main() {/ -i -#define all(x) x.begin(), x.end() -#define px real() -#define py imag() -#define mp make_pair -typedef complex<double> pt; -typedef vector<pt> vpt; -. -/int main() {/ -# add space before main -i +#include <bits/stdc++.h> +using namespace std; +using ll = long long; +const double EPS = 1e-8; +#include "../fontes/point.h" +#include "../fontes/monotone.h" -. -# add convex-hull right before that space -.r fontes/convex-hull.cpp -ke -# convex_hull -> convex_hull_ccw -/vpt convex_hull/ -.,/^}/s/convex_hull/convex_hull_ccw/ -# copy convex_hull_ccw -> convex_hull_cw -?vpt convex_hull_ccw? -/vpt convex_hull_ccw/,/^}/t-1 -/vpt convex_hull_ccw/ -.,.s/convex_hull_ccw/convex_hull_cw/ -.,/^}/s/<= 0)/>= 0)/ -# copy convex_hull_cw => convex_hull_ccw_colinear -?vpt convex_hull_cw? -/vpt convex_hull_cw/,/^}/t-1 -/vpt convex_hull_cw/ -.,.s/convex_hull_cw/convex_hull_ccw_colinear/ -.,/^}/s/>= 0)/< 0)/ -# copy convex_hull_ccw_colinear => convex_hull_cw_colinear -?vpt convex_hull_ccw_colinear? -/vpt convex_hull_ccw_colinear/,/^}/t-1 -/vpt convex_hull_ccw_colinear/ -.,.s/convex_hull_ccw_colinear/convex_hull_cw_colinear/ -.,/^}/s/< 0)/> 0)/ -?vpt convex_hull_cw_colinear?i - -. -# add space after -'ea - -. -$i - vpt convex; +int main() { + ios::sync_with_stdio(0); cin.tie(0); + vector<pt> convex; // 1 |* * // 0 |* * * // y +----- // x 0 1 2 - vpt points { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 }, { 2, 1 } }; + vector<pt> points { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 }, { 2, 1 } }; // 1 |3 2 // 0 |0 * 1 // y +----- // x 0 1 2 - convex = convex_hull_ccw(points); + convex = convex_hull(points); assert(convex.size() == 4); assert(convex[0] == pt(0, 0)); assert(convex[1] == pt(2, 0)); @@ -77,18 +30,18 @@ $i // 0 |0 * 3 // y +----- // x 0 1 2 - convex = convex_hull_cw(points); - assert(convex.size() == 4); - assert(convex[0] == pt(0, 0)); - assert(convex[1] == pt(0, 1)); - assert(convex[2] == pt(2, 1)); - assert(convex[3] == pt(2, 0)); + // convex = convex_hull_cw(points); + // assert(convex.size() == 4); + // assert(convex[0] == pt(0, 0)); + // assert(convex[1] == pt(0, 1)); + // assert(convex[2] == pt(2, 1)); + // assert(convex[3] == pt(2, 0)); // 1 |4 3 // 0 |0 1 2 // y +----- // x 0 1 2 - convex = convex_hull_ccw_colinear(points); + convex = convex_hull(points, true); assert(convex.size() == 5); assert(convex[0] == pt(0, 0)); assert(convex[1] == pt(1, 0)); @@ -100,15 +53,15 @@ $i // 0 |0 4 3 // y +----- // x 0 1 2 - convex = convex_hull_cw_colinear(points); - assert(convex.size() == 5); - assert(convex[0] == pt(0, 0)); - assert(convex[1] == pt(0, 1)); - assert(convex[2] == pt(2, 1)); - assert(convex[3] == pt(2, 0)); - assert(convex[4] == pt(1, 0)); + // convex = convex_hull_cw_colinear(points); + // assert(convex.size() == 5); + // assert(convex[0] == pt(0, 0)); + // assert(convex[1] == pt(0, 1)); + // assert(convex[2] == pt(2, 1)); + // assert(convex[3] == pt(2, 0)); + // assert(convex[4] == pt(1, 0)); - vpt ten_by_ten_grid; + vector<pt> ten_by_ten_grid; // 9 |* * * * * * * * * * // 8 |* * * * * * * * * * @@ -138,7 +91,7 @@ $i // 0 |0 * * * * * * * * 1 // y +------------------- // x 0 1 2 3 4 5 6 7 8 9 - convex = convex_hull_ccw(ten_by_ten_grid); + convex = convex_hull(ten_by_ten_grid); assert(convex.size() == 4); assert(convex[0] == pt(0., 0.)); assert(convex[1] == pt(9., 0.)); @@ -157,12 +110,12 @@ $i // 0 |0 * * * * * * * * 3 // y +------------------- // x 0 1 2 3 4 5 6 7 8 9 - convex = convex_hull_cw(ten_by_ten_grid); - assert(convex.size() == 4); - assert(convex[0] == pt(0., 0.)); - assert(convex[1] == pt(0., 9.)); - assert(convex[2] == pt(9., 9.)); - assert(convex[3] == pt(9., 0.)); + // convex = convex_hull_cw(ten_by_ten_grid); + // assert(convex.size() == 4); + // assert(convex[0] == pt(0., 0.)); + // assert(convex[1] == pt(0., 9.)); + // assert(convex[2] == pt(9., 9.)); + // assert(convex[3] == pt(9., 0.)); // 9 |R Q P O N M L K J I // 8 |S * * * * * * * * H @@ -176,7 +129,7 @@ $i // 0 |0 1 2 3 4 5 6 7 8 9 // y +------------------- // x 0 1 2 3 4 5 6 7 8 9 - convex = convex_hull_ccw_colinear(ten_by_ten_grid); + convex = convex_hull(ten_by_ten_grid, true); assert(convex.size() == 36); for (int i = 0; i < 9; i++) assert(convex[i+9*0] == pt(i-0, 0.)); for (int i = 0; i < 9; i++) assert(convex[i+9*1] == pt(9., i-0)); @@ -195,12 +148,10 @@ $i // 0 |0 Z Y X W V U T S R // y +------------------- // x 0 1 2 3 4 5 6 7 8 9 - convex = convex_hull_cw_colinear(ten_by_ten_grid); - assert(convex.size() == 36); - for (int i = 0; i < 9; i++) assert(convex[i+9*0] == pt(0., i-0)); - for (int i = 0; i < 9; i++) assert(convex[i+9*1] == pt(i-0, 9.)); - for (int i = 0; i < 9; i++) assert(convex[i+9*2] == pt(9., 9-i)); - for (int i = 0; i < 9; i++) assert(convex[i+9*3] == pt(9-i, 0.)); -. -w -EOF + // convex = convex_hull_cw_colinear(ten_by_ten_grid); + // assert(convex.size() == 36); + // for (int i = 0; i < 9; i++) assert(convex[i+9*0] == pt(0., i-0)); + // for (int i = 0; i < 9; i++) assert(convex[i+9*1] == pt(i-0, 9.)); + // for (int i = 0; i < 9; i++) assert(convex[i+9*2] == pt(9., 9-i)); + // for (int i = 0; i < 9; i++) assert(convex[i+9*3] == pt(9-i, 0.)); +}