Você está na página 1de 47

Notebook 100o

UNIFESO

7 de novembro de 2017
Sumário
1 Introdução 3
1.1 Template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Fast Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Bugs do Milênio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.4 Recomendações gerais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.5 Os 1010 mandamentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.6 Limites da representação de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.7 Quantidade de números primos de 1 até 10n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.8 Triângulo de Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.9 Fatoriais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.10 Tabela ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.11 Primos até 10.000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2 Estruturas de dados 10
2.1 Prex Sum 1D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2 Prex Sum 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3 BIT - Fenwick Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4 BIT - Fenwick Tree - Range updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.5 BIT - Fenwick Tree 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.6 BIT - Fenwick Tree 2D - Range Update . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.7 BIT - Fenwick Tree 2D - Comprimida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.8 Segment Tree 1D - Lazy Propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.9 Segment Tree 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.10 Segment Tree 2D Dinâmica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.11 Kd-Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.12 Treap / Cartesian Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.13 Treap / Cartesian Tree Implícita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.14 Sparse table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.15 Persistent Segment Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.16 Wavelet Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3 Paradigmas 19
3.1 Convex hull trick 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.2 Convex hull trick 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3 Convex hull trick 3 - Fully Dynamic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4 Divide and conquer optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.5 Knuth optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.6 Otimização com bitmask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4 Grafos 22
4.1 Ford Fulkerson . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.2 Edmonds Karp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.3 Dinic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.4 Min cost max ow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.5 Stoer-Wagner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.6 Tarjan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.7 Pontos de articulação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

1
SUMÁRIO 2

4.8 LCA (Sparce Table) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25


4.9 Posição de elemento em K passos em um ciclo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.10 Hopcroft Karp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.11 Blossom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.12 Centroid decomposition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.13 Heavy-Light Decomposition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.14 Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.15 Ahu - Tree isomorsmo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5 Matemática 30
5.1 Eliminação de Gauss com o XOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.2 Fórmula de Legendre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.3 Número de fatores primos de N! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.4 Trailing zeros in factorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.5 Número de divisores de N! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.6 Grundy Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.7 Baby-Step Giant-Step para Logaritmo Discreto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.8 Baby-Step Giant-Step FAST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.9 Números de Catalan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.10 Fórmulas úteis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.11 Fast Fourier Transform - FFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.12 Convolução Circular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
6 Processamento de Strings 35
6.1 Aho-Corasick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6.2 Rabin-Karp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6.3 Repetend: menor período de uma string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
6.4 Sux Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
6.5 Z Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.6 KMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
7 Geometria Computacional 38
7.1 Template - Júnior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.2 Menor círculo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
7.3 Kit de encolhimento - SBC 2016 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.4 Intersecção círculo e segmento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.5 Intersecção e distância entre segmentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
7.6 Closest pair problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.7 Área de união de retângulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.8 Distância entre segmento e ponto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
8 Miscelânea 45
8.1 Datas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
8.2 Hash C++11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
8.3 Mo's . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
8.4 Problema do histograma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
8.5 Sliding Window - Mediana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Capítulo 1

Introdução
1.1 Template
Digitar o template no inicio da prova.
NÃO esquecer de remover o f reopen()

#include <b i t s / s t d c ++.h> typedef p a i r <int , int > ii ;


using namespace s t d ;
#define a l l ( v ) ( v ) . b e g i n ( ) , ( v ) . end ( ) int main ( ) {
#define pb push_back freopen (" in " , " rt " , stdin ) ;
#define f s t f i r s t
#define snd s e c o n d return 0;
#define debug ( x ) c o u t << #x << " = " << x << endl ; }
typedef long long l l ;

1.2 Fast Input


Em casos extremos mete isso sem medo.

template<class num>inline void rd (num &x ) else


{ x=c− ' 0 ' ;
char c ; while ( i s d i g i t ( c=g e t c h a r ( ) ) )
while ( i s s p a c e ( c = g e t c h a r ( ) ) ) ; x=(x<<3)+(x<<1)+c− ' 0 ' ;
bool neg = false ; if ( neg )
if ( ! i s d i g i t ( c ) ) x=−x ;
neg=(c=='− ' ) , x=0; }

1.3 Bugs do Milênio


Cortesia da ITA.

Erros teóricos: • Vericar com calma (fazer as contas direito) para ver
se o innito é tão innito quanto parece.
• Não ler o enunciado do problema com calma.
• Assumir algum fato sobre a solução na pressa. • Vericar se operações com innito estouram 31 bits.
• Não reler os limites do problema antes de submeter. • Usar multiplicação de int's e estourar 32 bits (por
• Quando adaptar um algoritmo, atentar para todos os
exemplo, checar sinais usando a ∗ b > 0).
detalhes da estrutura do algoritmo, se devem (ou não) Erros de casos extremos:
ser modicados (ex:marcação de vértices/estados).
• O problema pode ser NP, disfarçado ou mesmo sem • Testou caso n = 0? n = 1? n = M AXN ? Muitas
limites especicados. Nesse caso a solução é bronca vezes tem que tratar separado.
mesmo. Não é hora de tentar ganhar o prêmio nobel.
• Pense em todos os casos que podem ser considerados
Erros com valor máximo de variável: casos extremos ou casos isolados.

3
CAPÍTULO 1. INTRODUÇÃO 4

• Casos extremos podem atrapalhar não só no algo- • O exercício é um caso particular que pode (e está pre-
ritmo, mas em coisas como construir alguma estrutura cisando) ser otimizado e não usar direto a biblioteca?
(ex: lista de adj em grafos).
Erros em doubles:
• Não esquecer de self-loops ou multiarestas em grafos.
• Em problemas de caminho Euleriano, vericar se o • Primeiro, evitar (a não ser que seja necessário ou mais
grafo é conexo. simples a solução) usar f loat/double. E.g. conta que
só precisa de 2 casas decimais pode ser feita com in-
Erros de desatenção em implementação: teiro e depois %100.
• Errar ctrl-C/ctrl-V em código. Muito comum. • Sempre usar double, não f loat (a não ser que o enun-
• Colocar igualdade dentro de if ? (if (a = 0)continue;) ciado peça explicitamente).
• Esquecer de inicializar variável. • Testar igualdade com tolerância (absoluta, e talvez re-
• Trocar break por continue (ou vice-versa). lativa).
• Declarar variável global e variável local com mesmo • Cuidado com erros de imprecisão, em particular evitar
nome (é pedir pra dar merda...). ao máximo subtrair dois números praticamente iguais.
Erros de implementação: Outros erros:
• Denir variável com tipo errado (int por double, int • Evitar (a não ser que seja necessário) alocação dinâ-
por char). mica de memória.
• Não usar variável com nome max e min. • Não usar STL desnecessariamente (ex: vector quando
• Não esquecer que .size() é unsigned. um array normal dá na mesma), mas usar se facili-
• Lembrar que 1 é int, ou seja, se zer long long a = tar (ex: nomes associados a vértices de um grafo -
1 << 40;, não irá funcionar (o ideal é fazer map < string, int >) ou se precisar (ex: um algo-
long long a = 1LL << 40;). ritmo O(nlogn) que usa < set > é necessário para
passar no tempo).
Erros em limites:
• Não inicializar variável a cada teste (zerou vetores?
• Qual o ordem do tempo e memória? 108 é uma re- zerou variável que soma algo? zerou com zero? era
ferência para tempo. Sempre vericar rapidamente pra zerar com zero, com -1 ou com INF?).
a memória, apesar de que o limite costuma ser bem
grande. • Saída está formatada corretamente?
• A constante pode ser muito diminuída com um al- • Declarou vetor com tamanho suciente?
goritmo melhor (ex: húngaro no lugar de uxo) ou • Cuidado ao tirar o módulo de número negativo. Ex.:
com operações mais rápidas (ex: divisões são lentas, x%n não dá o resultado esperado se x é negativo, fazer
bitwise é rápido)? (x%n + n)%n.

1.4 Recomendações gerais


Cortesia da PUC-RJ.

ANTES DA PROVA
• Revisar os algoritmos disponíveis na biblioteca.
• Revisar a referência STL.
• Reler este roteiro.
• Ouvir o discurso motivacional do técnico.
ANTES DE IMPLEMENTAR UM PROBLEMA
• Quem for implementar deve relê-lo antes.
• Peça todas as clarications que forem necessárias.
• Marque as restrições e faça contas com os limites da entrada.
• Teste o algoritmo no papel e convença outra pessoa de que ele funciona.
• Planeje a resolução para os problemas grandes: a equipe se junta para denir as estruturas de dados, mas cada
pessoa escreve uma função.
CAPÍTULO 1. INTRODUÇÃO 5

DEBUGAR UM PROGRAMA
• Ao encontrar um bug, escreva um caso de teste que o dispare.
• Reimplementar trechos de programas entendidos errados.
• Em caso de RE, procure todos os [, / e %.

1.5 Os 1010 mandamentos


Também cortesia da PUC-RJ.

0. Não dividirás por zero.


1. Não alocarás dinamicamente.
2. Compararás números de ponto utuante usando EPS.
3. Vericarás se o grafo pode ser desconexo.
4. Vericarás se as arestas do grafo podem ter peso negativo.
5. Vericarás se pode haver mais de uma aresta ligando dois vértices.
6. Conferirás todos os índices de uma programação dinâmica.
7. Reduzirás o branching factor da DFS.
8. Farás todos os cortes possíveis em uma DFS.
9. Tomarás cuidado com pontos coincidentes e com pontos colineares.
CAPÍTULO 1. INTRODUÇÃO 6

1.6 Limites da representação de dados


tipo bits mínimo .. máximo precisão decimal
char 8 0 .. 127 2
signed char 8 −128 .. 127 2
unsigned char 8 0 .. 255 2
short 16 −32.768 .. 32.767 4
unsigned short 16 0 .. 65.535 4
int 32 −2 × 109 .. 2 × 109 9
unsigned int 32 0 .. 4 × 109 9
long long 64 −9 × 1018 .. 9 × 1018 18
unsigned long long 64 0 .. 18 × 1018 19

tipo bits expoente precisão decimal


oat 32 38 6
double 64 308 15
long double 80 19.728 18

1.7 Quantidade de números primos de 1 até 10n


É sempre verdade que n/ln(n) < pi(n) < 1.26 ∗ n/ln(n).
pi(101 ) = 4 pi(102 ) = 25 pi(103 ) = 168
pi(104 ) = 1.229 pi(105 ) = 9.592 pi(106 ) = 78.498
pi(107 ) = 664.579 pi(108 ) = 5.761.455 pi(109 ) = 50.847.534

1.8 Triângulo de Pascal


n\p 0 1 2 3 4 5 6 7 8 9 10
0 1
1 1 1
2 1 2 1
3 1 3 3 1
4 1 4 6 4 1
5 1 5 10 10 5 1
6 1 6 15 20 15 6 1
7 1 7 21 35 35 21 7 1
8 1 8 28 56 70 56 28 8 1
9 1 9 36 84 126 126 84 36 9 1
10 1 10 45 120 210 252 210 120 45 10 1

C(33, 16) 1.166.803.110 limite do int


C(34, 17) 2.333.606.220 limite do unsigned int
C(66, 33) 7.219.428.434.016.265.740 limite do long long
C(67, 33) 14.226.520.737.620.288.370 limite do unsigned long long
CAPÍTULO 1. INTRODUÇÃO 7

1.9 Fatoriais
Fatoriais até 20 com os limites de tipo.
0! 1
1! 1
2! 2
3! 6
4! 24
5! 120
6! 720
7! 5.040
8! 40.320
9! 362.880
10! 3.628.800
11! 39.916.800
12! 479.001.600 limite do unsigned int
13! 6.227.020.800
14! 87.178.291.200
15! 1.307.674.368.000
16! 20.922.789.888.000
17! 355.687.428.096.000
18! 6.402.373.705.728.000
19! 121.645.100.408.832.000
20! 2.432.902.008.176.640.000 limite do unsigned long long

1.10 Tabela ASCII


CAPÍTULO 1. INTRODUÇÃO 8

1.11 Primos até 10.000


Existem 1.229 números primos até 10.000.
2 3 5 7 11 13 17 19 23 29 31
37 41 43 47 53 59 61 67 71 73 79
83 89 97 101 103 107 109 113 127 131 137
139 149 151 157 163 167 173 179 181 191 193
197 199 211 223 227 229 233 239 241 251 257
263 269 271 277 281 283 293 307 311 313 317
331 337 347 349 353 359 367 373 379 383 389
397 401 409 419 421 431 433 439 443 449 457
461 463 467 479 487 491 499 503 509 521 523
541 547 557 563 569 571 577 587 593 599 601
607 613 617 619 631 641 643 647 653 659 661
673 677 683 691 701 709 719 727 733 739 743
751 757 761 769 773 787 797 809 811 821 823
827 829 839 853 857 859 863 877 881 883 887
907 911 919 929 937 941 947 953 967 971 977
983 991 997 1009 1013 1019 1021 1031 1033 1039 1049
1051 1061 1063 1069 1087 1091 1093 1097 1103 1109 1117
1123 1129 1151 1153 1163 1171 1181 1187 1193 1201 1213
1217 1223 1229 1231 1237 1249 1259 1277 1279 1283 1289
1291 1297 1301 1303 1307 1319 1321 1327 1361 1367 1373
1381 1399 1409 1423 1427 1429 1433 1439 1447 1451 1453
1459 1471 1481 1483 1487 1489 1493 1499 1511 1523 1531
1543 1549 1553 1559 1567 1571 1579 1583 1597 1601 1607
1609 1613 1619 1621 1627 1637 1657 1663 1667 1669 1693
1697 1699 1709 1721 1723 1733 1741 1747 1753 1759 1777
1783 1787 1789 1801 1811 1823 1831 1847 1861 1867 1871
1873 1877 1879 1889 1901 1907 1913 1931 1933 1949 1951
1973 1979 1987 1993 1997 1999 2003 2011 2017 2027 2029
2039 2053 2063 2069 2081 2083 2087 2089 2099 2111 2113
2129 2131 2137 2141 2143 2153 2161 2179 2203 2207 2213
2221 2237 2239 2243 2251 2267 2269 2273 2281 2287 2293
2297 2309 2311 2333 2339 2341 2347 2351 2357 2371 2377
2381 2383 2389 2393 2399 2411 2417 2423 2437 2441 2447
2459 2467 2473 2477 2503 2521 2531 2539 2543 2549 2551
2557 2579 2591 2593 2609 2617 2621 2633 2647 2657 2659
2663 2671 2677 2683 2687 2689 2693 2699 2707 2711 2713
2719 2729 2731 2741 2749 2753 2767 2777 2789 2791 2797
2801 2803 2819 2833 2837 2843 2851 2857 2861 2879 2887
2897 2903 2909 2917 2927 2939 2953 2957 2963 2969 2971
2999 3001 3011 3019 3023 3037 3041 3049 3061 3067 3079
3083 3089 3109 3119 3121 3137 3163 3167 3169 3181 3187
3191 3203 3209 3217 3221 3229 3251 3253 3257 3259 3271
3299 3301 3307 3313 3319 3323 3329 3331 3343 3347 3359
3361 3371 3373 3389 3391 3407 3413 3433 3449 3457 3461
3463 3467 3469 3491 3499 3511 3517 3527 3529 3533 3539
3541 3547 3557 3559 3571 3581 3583 3593 3607 3613 3617
3623 3631 3637 3643 3659 3671 3673 3677 3691 3697 3701
3709 3719 3727 3733 3739 3761 3767 3769 3779 3793 3797
3803 3821 3823 3833 3847 3851 3853 3863 3877 3881 3889
3907 3911 3917 3919 3923 3929 3931 3943 3947 3967 3989
4001 4003 4007 4013 4019 4021 4027 4049 4051 4057 4073
4079 4091 4093 4099 4111 4127 4129 4133 4139 4153 4157
CAPÍTULO 1. INTRODUÇÃO 9

4159 4177 4201 4211 4217 4219 4229 4231 4241 4243 4253
4259 4261 4271 4273 4283 4289 4297 4327 4337 4339 4349
4357 4363 4373 4391 4397 4409 4421 4423 4441 4447 4451
4457 4463 4481 4483 4493 4507 4513 4517 4519 4523 4547
4549 4561 4567 4583 4591 4597 4603 4621 4637 4639 4643
4649 4651 4657 4663 4673 4679 4691 4703 4721 4723 4729
4733 4751 4759 4783 4787 4789 4793 4799 4801 4813 4817
4831 4861 4871 4877 4889 4903 4909 4919 4931 4933 4937
4943 4951 4957 4967 4969 4973 4987 4993 4999 5003 5009
5011 5021 5023 5039 5051 5059 5077 5081 5087 5099 5101
5107 5113 5119 5147 5153 5167 5171 5179 5189 5197 5209
5227 5231 5233 5237 5261 5273 5279 5281 5297 5303 5309
5323 5333 5347 5351 5381 5387 5393 5399 5407 5413 5417
5419 5431 5437 5441 5443 5449 5471 5477 5479 5483 5501
5503 5507 5519 5521 5527 5531 5557 5563 5569 5573 5581
5591 5623 5639 5641 5647 5651 5653 5657 5659 5669 5683
5689 5693 5701 5711 5717 5737 5741 5743 5749 5779 5783
5791 5801 5807 5813 5821 5827 5839 5843 5849 5851 5857
5861 5867 5869 5879 5881 5897 5903 5923 5927 5939 5953
5981 5987 6007 6011 6029 6037 6043 6047 6053 6067 6073
6079 6089 6091 6101 6113 6121 6131 6133 6143 6151 6163
6173 6197 6199 6203 6211 6217 6221 6229 6247 6257 6263
6269 6271 6277 6287 6299 6301 6311 6317 6323 6329 6337
6343 6353 6359 6361 6367 6373 6379 6389 6397 6421 6427
6449 6451 6469 6473 6481 6491 6521 6529 6547 6551 6553
6563 6569 6571 6577 6581 6599 6607 6619 6637 6653 6659
6661 6673 6679 6689 6691 6701 6703 6709 6719 6733 6737
6761 6763 6779 6781 6791 6793 6803 6823 6827 6829 6833
6841 6857 6863 6869 6871 6883 6899 6907 6911 6917 6947
6949 6959 6961 6967 6971 6977 6983 6991 6997 7001 7013
7019 7027 7039 7043 7057 7069 7079 7103 7109 7121 7127
7129 7151 7159 7177 7187 7193 7207 7211 7213 7219 7229
7237 7243 7247 7253 7283 7297 7307 7309 7321 7331 7333
7349 7351 7369 7393 7411 7417 7433 7451 7457 7459 7477
7481 7487 7489 7499 7507 7517 7523 7529 7537 7541 7547
7549 7559 7561 7573 7577 7583 7589 7591 7603 7607 7621
7639 7643 7649 7669 7673 7681 7687 7691 7699 7703 7717
7723 7727 7741 7753 7757 7759 7789 7793 7817 7823 7829
7841 7853 7867 7873 7877 7879 7883 7901 7907 7919 7927
7933 7937 7949 7951 7963 7993 8009 8011 8017 8039 8053
8059 8069 8081 8087 8089 8093 8101 8111 8117 8123 8147
8161 8167 8171 8179 8191 8209 8219 8221 8231 8233 8237
8243 8263 8269 8273 8287 8291 8293 8297 8311 8317 8329
8353 8363 8369 8377 8387 8389 8419 8423 8429 8431 8443
8447 8461 8467 8501 8513 8521 8527 8537 8539 8543 8563
8573 8581 8597 8599 8609 8623 8627 8629 8641 8647 8663
8669 8677 8681 8689 8693 8699 8707 8713 8719 8731 8737
8741 8747 8753 8761 8779 8783 8803 8807 8819 8821 8831
8837 8839 8849 8861 8863 8867 8887 8893 8923 8929 8933
8941 8951 8963 8969 8971 8999 9001 9007 9011 9013 9029
9041 9043 9049 9059 9067 9091 9103 9109 9127 9133 9137
9151 9157 9161 9173 9181 9187 9199 9203 9209 9221 9227
9239 9241 9257 9277 9281 9283 9293 9311 9319 9323 9337
9341 9343 9349 9371 9377 9391 9397 9403 9413 9419 9421
9431 9433 9437 9439 9461 9463 9467 9473 9479 9491 9497
9511 9521 9533 9539 9547 9551 9587 9601 9613 9619 9623
9629 9631 9643 9649 9661 9677 9679 9689 9697 9719 9721
9733 9739 9743 9749 9767 9769 9781 9787 9791 9803 9811
9817 9829 9833 9839 9851 9857 9859 9871 9883 9887 9901
9907 9923 9929 9931 9941 9949 9967 9973
Capítulo 2

Estruturas de dados
2.1 Prex Sum 1D
Soma a..b em O(1).

#define MAXN 1000 p r e f i x [ i ] = p r e f i x [ i −1]+ a r r [ i ] ;


int a r r [MAXN] ; }
int p r e f i x [MAXN] ;
int g e t ( int a , int b ) {
void b u i l d ( int n ) { return p r e f i x [ b ] − p r e f i x [ a − 1 ] ;
prefix [ 0 ] = 0; }
for ( int i = 1 ; i <= n ; i ++) // arr 1− i n d e x a d o

2.2 Prex Sum 2D


Soma um subretângulo em ponto em O(1).
Indexado em 1.

#define MAXN 1000


int mat [MAXN] [MAXN] , p r e f i x [MAXN] [MAXN] ;
void b u i l d ( ) {
for ( int i = 1 ; i <= n ; i ++)
for ( int j = 1 ; j <= n ; j ++)
p r e f i x [ i ] [ j ] = mat [ i ] [ j ] + p r e f i x [ i − 1 ] [ j ] + p r e f i x [ i ] [ j − 1 ] − p r e f i x [ i − 1 ] [ j − 1 ] ;
}

int g e t ( int x1 , int y1 , int x2 , int y2 ) {


return p r e f i x [ x2 ] [ y2 ] − p r e f i x [ x1 − 1 ] [ y2 ] − p r e f i x [ x2 ] [ y1 − 1 ] + p r e f i x [ x1 − 1 ] [ y1 − 1 ] ;
}

2.3 BIT - Fenwick Tree


Soma 1..N e update em ponto em O(logn).

#define MAXN 10000 int g e t ( int x ) {


int b i t [MAXN] ; int ans = 0 ;
void update ( int x , int v a l ) { for ( ; x ; x−=x&−x )
for ( ; x < MAXN; x+=x&−x ) ans += b i t [ x ] ;
b i t [ x ] += v a l ; return ans ;
} }

2.4 BIT - Fenwick Tree - Range updates


Consulta em range e update em range (v[i..j]+=v) em O(logn).

10
CAPÍTULO 2. ESTRUTURAS DE DADOS 11

}
vector< int> bit1 , bit2 ;
void init ( int n){ void update ( int i, int j, int v){
b i t 1 . a s s i g n ( n+1, 0 ) ; update ( b i t 1 , i , v) ;
b i t 2 . a s s i g n ( n+1, 0 ) ; update ( b i t 1 , j +1, −v ) ;
} update ( b i t 2 , i , v ∗ ( i − 1) ) ;
update ( b i t 2 , j +1, −v ∗ j ) ;
int r s q ( v e c t o r <int > &b i t , int i ){ }
int ans = 0 ;
for ( ; i ; i −=i&− i ) int r s q ( int i ) {
ans += b i t [ i ] ; return r s q ( b i t 1 , i ) ∗ i − rsq ( bit2 , i ) ;
return ans ; }
}
int r s q ( int i , int j ){
void update ( v e c t o r <int > &b i t , int i, int v){ return r s q ( j ) − r s q ( i − 1) ;
for ( ; i < b i t . s i z e ( ) ; i+=i&− i ) }
b i t [ i ] += v ;

2.5 BIT - Fenwick Tree 2D


Soma um subretângulo e update em ponto em O(log 2 n).
#define MAXN 1000 for ( ; x ; x−=x&−x )
int b i t [MAXN] [MAXN] ; for ( int j = y ; j ; j −=j&− j )
ans += b i t [ x ] [ j ] ;
void update ( int x , int y , int v a l ) { return ans ;
for ( ; x < MAXN; x+=x&−x ) }
for ( int j = y ; j < MAXN; j+=j&− j )
b i t [ x ] [ j ] += v a l ; int g e t ( int x1 , int y1 , int x2 , int y2 ) {
} return g e t ( x2 , y2 ) − g e t ( x1 −1, y2 ) − g e t ( x2 , y1
− 1) + g e t ( x1 − 1, y1 − 1) ;
int get ( int
x, int y){ }
int ans = 0 ;

2.6 BIT - Fenwick Tree 2D - Range Update


Update em range, consulta em ponto e em range.
#define MAXN 505 update ( 1 , x1 , y2 +1, v a l ∗ y2 ) ;
update ( 1 , x2 +1, y1 , v a l ∗ ( y1 − 1) ) ;
l l b i t [ 4 ] [MAXN + 5 0 ] [MAXN + 5 0 ] ; update ( 1 , x2 +1, y2 +1, − v a l ∗ y2 ) ;

void update ( int node , int x , int y , l l v){ update ( 2 , x1 , y1 , v a l ∗ (1 − x1 ) ) ;


for ( ; x <= MAXN; x +=x&−x ) update ( 2 , x1 , y2 +1, ( x1 − 1) ∗ v a l ) ;
for ( int j = y ; j <= MAXN; j+=j&− j ) update ( 2 , x2 +1, y1 , v a l ∗ x2 ) ;
b i t [ node ] [ x ] [ j ] += v ; update ( 2 , x2 +1, y2 +1, −x2 ∗ v a l ) ;
}
update ( 3 , x1 , y1 , ( x1 − 1) ∗ ( y1 − 1) ∗ v a l ) ;
l l query ( int
node , int
x, y){ int update ( 3 , x1 , y2 +1, −y2 ∗ ( x1 − 1) ∗ v a l ) ;
l l ans = 0 ; update ( 3 , x2 +1, y1 , −x2 ∗ ( y1 − 1) ∗ v a l ) ;
for
( ; x ; x−=x&−x ) update ( 3 , x2 +1, y2 +1, x2 ∗ y2 ∗ v a l ) ;
for int
( j = y ; j ; j −=j&− j ) }
ans += b i t [ node ] [ x ] [ j ] ;
return ans ; l l queryPoint ( x, int y){ int
} return
query ( 0 , x , y ) ∗ x ∗ y + query ( 1 , x , y )
∗ x + query ( 2 , x , y ) ∗ y + query ( 3 , x , y ) ;
void updateSubMatrix ( int
x1 , int y1 , int x2 , int }
y2 , l l v a l ) {
update ( 0 , x1 , y1 , v a l ) ; l l querySubMatrix ( intx1 , int
y1 , int
x2 , int y2 ) {
update ( 0 , x1 , y2 + 1 , − v a l ) ; returnq u e r y P o i n t ( x2 , y2 ) − q u e r y P o i n t ( x1 − 1 ,
update ( 0 , x2 + 1 , y1 , − v a l ) ; y2 ) − q u e r y P o i n t ( x2 , y1 − 1 ) + q u e r y P o i n t (
update ( 0 , x2 +1, y2 +1, v a l ) ; x1 − 1 , y1 − 1 ) ;
}
update ( 1 , x1 , y1 , v a l ∗ (1 − y1 ) ) ;

2.7 BIT - Fenwick Tree 2D - Comprimida


Operações possíveis com x e y até 105
CAPÍTULO 2. ESTRUTURAS DE DADOS 12

• Inserir 1 em uma posição do grid.


• Remover 1 em uma posição do grid.
• Contar a quantidade de 1's em um retângulo.

O(Qlog 2 N ).

for ( int i = x ; i < LIM ; i+=i&− i )


#include <e x t /pb_ds/ a s s o c _ c o n t a i n e r . hpp> bit [ i ] . erase ( i i (y , x) ) ;
#include <e x t /pb_ds/ t r e e _ p o l i c y . hpp> }
using namespace s t d ;
using namespace __gnu_pbds ; int query ( int x , int y ) {
typedef p a i r <int , int > p i i ; int ans = 0 ;
typedef t r e e <p i i , null_type , l e s s <p i i >, for ( int i = x ; i ; i −=i&− i )
rb_tree_tag , t r e e _ o r d e r _ s t a t i s t i c s _ n o d e _ u p d a t e ans += b i t [ i ] . order_of_key ( i i ( y+1, 0) ) ;
> OST; return ans ;
}
#define N 100010
OST b i t [N ] ; int query ( intx1 , int y1 , int
x2 , int
y2 ) {
void i n s e r t ( int x , int y ) { return query ( x2 , y2 ) − query ( x2 , y1 − 1) − query (
for ( int i = x ; i < N; i+=i&− i ) x1 − 1, y2 ) + query ( x1 − 1, y1 − 1) ;
bit [ i ] . insert ( i i (y , x) ) ; }
}

void int int


// K− t h element
remove ( x, y){ // find_by_order ( ) ;

2.8 Segment Tree 1D - Lazy Propagation


O build está gerando uma árvore com zeros, alterar quando houver valores iniciais

#define NMAX 100010 void update ( int idx , int l, int r, int i, int j,
#define mid ( ( l + r ) / 2) int val ){
#define l l long long p r o p a g a t i o n ( idx , l , r ) ;

l l t r e e [NMAX ∗ 4 ] , l a z y [NMAX ∗ 4 ] ; if ( j < l or i > r )


return ;
void build ( int idx , int l, int r ){
lazy [ idx ] = 0; if ( l >= i && r <= j ) {
t r e e [ idx ] = 0; l a z y [ i d x ] += v a l ;
p r o p a g a t i o n ( idx , l , r ) ;
if ( l == r) return ;
return ; }

b u i l d ( i d x ∗ 2 , l , mid ) ; update ( i d x ∗ 2 , l , mid , i , j , v a l ) ;


b u i l d ( i d x ∗ 2 + 1 , mid + 1 , r ) ; update ( i d x ∗ 2 + 1 , mid + 1 , r , i , j , v a l ) ;
} t r e e [ idx ] = t r e e [ idx ∗ 2] + t r e e [ idx ∗ 2 + 1 ] ;
}
void p r o p a g a t i o n ( int idx , int l, int r ){
if ( l a z y [ i d x ] ) { l l get ( int idx , int l, intr, int i, int j ){
t r e e [ i d x ] += ( l l ) ( r − l + 1 ) ∗ l a z y [ i d x ] ; p r o p a g a t i o n ( idx , l , r ) ;

if ( l != r ) { if ( j < l or i > r )
l a z y [ i d x ∗ 2 ] += l a z y [ i d x ] ; return 0 ;
l a z y [ i d x ∗ 2 + 1 ] += l a z y [ i d x ] ;
} if ( l >= i && r <= j )
return t r e e [ i d x ] ;
lazy [ idx ] = 0;
} return g e t ( i d x ∗ 2 , l , mid , i , j ) + g e t ( i d x ∗ 2
} + 1 , mid + 1 , r , i , j ) ;
}

2.9 Segment Tree 2D


Quando a consulta é em uma distância de manhattan d, basta rotacionar o grid 45o . Todo ponto (x, y) vira (x+y, x-y).
A consulta ca ((x+d, y+d), (x-d, y-d))
CAPÍTULO 2. ESTRUTURAS DE DADOS 13

if ( l x > x2 | | rx < x1 )
#define MAXN 1030 return 0 ;
if ( l x >= x1 && rx <= x2 )
int t r e e [ 4 ∗MAXN] [ 4 ∗MAXN] ; return g e t y ( idxx , idxy , ly , ry , y1 , y2 ) ;
return g e t x ( i d x x ∗ 2 , lx , ( l x+rx ) / 2 , idxy , ly , ry
void b u i l d y ( int idxx , int lx , int rx , int idxy , , x1 , x2 , y1 , y2 ) +
int ly , int ry ) { g e t x ( i d x x ∗ 2+1 , ( l x+rx ) /2+1 , rx , idxy , ly , ry ,
if ( l y == ry ) { x1 , x2 , y1 , y2 ) ;
if ( l x == rx ) }
t r e e [ idxx ] [ idxy ] = 0;
else void updatey ( int idxx , int lx , int rx , int
// Valor inicial
idxy ,
t r e e [ idxx ] [ idxy ] = t r e e [ idxx ∗ 2 ] [ idxy ] + int ly , int ry , int py , int v a l ) {
t r e e [ idxx ∗2+1][ idxy ] ; if ( l y > py | | ry < py )
return ; return ;
} if ( l y == ry ) {
b u i l d y ( idxx , lx , rx , i d x y ∗ 2 , ly , ( l y+ry ) / 2 ) ; if ( l x == rx )
b u i l d y ( idxx , lx , rx , i d x y ∗ 2+1 , ( l y+ry ) /2+1 , ry ) t r e e [ i d x x ] [ i d x y ] += v a l ;
; else
t r e e [ idxx ] [ idxy ] = t r e e [ idxx ] [ idxy ∗2] + t r e e [ t r e e [ idxx ] [ idxy ] = t r e e [ idxx ∗ 2 ] [ idxy ] +
idxx ] [ idxy ∗2+1]; t r e e [ idxx ∗2+1][ idxy ] ;
} return ;
}
void b u i l d x ( int idx , int lx , int rx , int ly , int updatey ( idxx , lx , rx , i d x y ∗ 2 , ly , ( l y+ry ) / 2 , py
ry ) { , val ) ;
if ( l x != rx ) { updatey ( idxx , lx , rx , i d x y ∗ 2+1 , ( l y+ry ) /2+1 , ry
b u i l d x ( i d x ∗ 2 , lx , ( l x+rx ) / 2 , ly , ry ) ; , py , v a l ) ;
b u i l d x ( i d x ∗ 2+1 , ( l x+rx ) /2+1 , rx , ly , ry ) ; t r e e [ idxx ] [ idxy ] = t r e e [ idxx ] [ idxy ∗2] + t r e e [
} idxx ] [ idxy ∗2+1];
b u i l d y ( idx , lx , rx , 1 , ly , ry ) ; }
}
void updatex ( int idxx , int lx , int rx , int idxy ,
int gety (int idxx , int idxy , int
ly , int
ry , int int ly , int ry , int px , int py , int v a l ) {
y1 ,int y2 ) { if ( l x > px | | rx < px )
if( l y > y2 | | ry < y1 ) return ;
return 0; if ( l x != rx ) {
if( l y >= y1 && ry <= y2 ) updatex ( i d x x ∗ 2 , lx , ( l x+rx ) / 2 , idxy , ly , ry ,
return t r e e [ idxx ] [ idxy ] ; px , py , v a l ) ;
return g e t y ( idxx , i d x y ∗ 2 , ly , ( l y+ry ) / 2 , y1 , y2 updatex ( i d x x ∗ 2+1 , ( l x+rx ) /2+1 , rx , idxy , ly ,
) + g e t y ( idxx , i d x y ∗ 2+1 , ( l y+ry ) /2+1 , ry , ry , px , py , v a l ) ;
y1 , y2 ) ; }
} updatey ( idxx , lx , rx , idxy , ly , ry , py , v a l ) ;
}
int getx ( int idxx , int lx , int rx , int idxy , int
ly , int ry , int x1 , int x2 , int y1 , int y2 ) {

2.10 Segment Tree 2D Dinâmica


Não consegue comprimir usa essa.

if ( l y > y2 | | ry < y1 )
struct node1 { return 0 ;
int val ; if ( l y >= y1 && ry <= y2 )
node1 ∗ l , ∗ r ; return t r e e −>v a l ;
node1 ( ) { int ans = 0 ;
val = 0; int mid = ( l y+ry ) / 2 ;
l = r = 0; if ( t r e e −>l )
} ans += g e t y ( t r e e −>l , ly , mid , y1 , y2 ) ;
}; if ( t r e e −>r )
ans += g e t y ( t r e e −>r , mid+1, ry , y1 , y2 ) ;
struct node2 { return ans ;
node1 ∗ t r e e ; }
node2 ∗ l , ∗ r ;
node2 ( ) { int g e t x ( node2 ∗ t r e e , int int
lx , rx ,int ly , int
tree = newnode1 ( ) ; ry , int x1 ,int int
x2 , int
y1 , y2 ) {
l = r = 0; if ( ! t r e e | | ! t r e e −>t r e e )return 0;
} if ( l x > x2 | | rx < x1 )
}; return 0;
if ( l x >= x1 && rx <= x2 )
int g e t y ( node1 ∗ t r e e , int ly , int ry , int y1 , int return g e t y ( t r e e −>t r e e , ly , ry , y1 , y2 ) ;
y2 ) { int ans = 0 ;
if (! tree ) return 0; int mid = ( l x+rx ) / 2 ;
CAPÍTULO 2. ESTRUTURAS DE DADOS 14

if( t r e e −>l ) updatey ( t r e e −>r , l , r , lx , rx , mid+1, ry , py


ans += g e t x ( t r e e −>l , lx , mid , ly , ry , x1 , x2 , , val ) ;
y1 , y2 ) ; }
if( t r e e −>r ) t r e e −>v a l = ( t r e e −>l ? t r e e −>l −>v a l : 0 ) + ( t r e e −>r
ans += g e t x ( t r e e −>r , mid+1, rx , ly , ry , x1 , x2 , ? t r e e −>r −>v a l : 0 ) ;
y1 , y2 ) ; }
return ans ;
} void updatex ( node2 ∗ t r e e , int lx , int rx , int ly ,
int ry , int px , int py , int v a l ) {
void updatey ( node1 ∗ t r e e , node1 ∗ l , node1 ∗ r , int if ( l x > px | | rx < px )
lx , int rx , int ly , int ry , int py , int v a l ) { return ;
if ( l y > py | | ry < py ) if ( l x != rx ) {
return ; int mid = ( l x+rx ) / 2 ;
if ( l y == ry ) { if ( px <= mid ) {
if ( l x == rx ) if ( ! t r e e −>l ) t r e e −>l = new node2 ( ) ;
t r e e −>v a l = v a l ; updatex ( t r e e −>l , lx , mid , ly , ry , px , py ,
else val ) ;
t r e e −>v a l = ( ! l ? 0 : l −>v a l ) + ( ! r ? 0 : r −>v a l ) ; }
return ; else {
} if ( ! t r e e −>r ) t r e e −>r = new
node2 ( ) ;
int mid = ( l y+ry ) / 2 ; updatex ( t r e e −>r , mid+1, rx , ly , ry , px ,
if ( py <= mid ) { py , v a l ) ;
if ( ! t r e e −>l ) t r e e −>l = new node1 ( ) ; }
l = l ? l −>l ? l −>l : 0 : 0 ; }
r = r ? r −>l ? r −>l : 0 : 0 ; updatey ( t r e e −>t r e e , ! t r e e −>l ? 0 : t r e e −>l −>t r e e
updatey ( t r e e −>l , l , r , lx , rx , ly , mid , py , , ! t r e e −>r ? 0 : t r e e −>r −>t r e e , lx , rx , ly ,
val ) ; ry , py , v a l ) ;
} }
else {
if ( ! t r e e −>r ) t r e e −>r = new node1 ( ) ;
new
// IN MAIN
l = l ? l −>r ? l −>r : 0 : 0 ; node2 ∗ s e g = node2 ( ) ;
r = r ? r −>r ? r −>r : 0 : 0 ;

2.11 Kd-Tree
Encontra os K pontos mais próximos de um dado ponto O(klog(k)log(n)).

#define MAXN 10100


// k− n e a r e s t neighbor query , O( k log (k) log (n) )

double double y , int


on average
v e c t o r <p o i n t > query ( x, k =
double d i s t ( int x , int y , int xx , int yy ) { 1) {
return hypot ( x − xx , y − yy ) ; perform_query ( x , y , k , 0 , n , false ) ; //
} recurse
v e c t o r <p o i n t > p o i n t s ;
while ( ! pq . empty ( ) ) { // c o l l e c t p o i n t s
p o i n t s . push_back ( ∗ pq . top ( ) . s e c o n d ) ;
struct p o i n t {
// 2D point object
pq . pop ( ) ;
double x , y ; }
p o i n t ( double x = 0, double y = 0) : x ( x ) , y ( y ) r e v e r s e ( p o i n t s . b e g i n ( ) , p o i n t s . end ( ) ) ;
{} return points ;
}; }
private :
void b u i l d ( int L , int R, bool
// the " hyperplane split ", use comparators for all // build is O( n log n) using divide and conquer
dvx ) {
bool cmpx ( const const return if (L >= R) return ;
dimensions
p o i n t& a , p o i n t& b ) {
a . x < b . x;} int M = (L + R) / 2 ;
bool cmpy ( const p o i n t& a , const p o i n t& b ) { return // get median i n O( n ) , split x− c o o r d i n a t e if
a . y < b . y;} dvx is true
nth_element ( t r e e+L , t r e e+M, t r e e+R, dvx ?cmpx
struct k d t r e e { : cmpy ) ;
point ∗ tree ; b u i l d (L , M, ! dvx ) ; b u i l d (M+1, R, ! dvx ) ;
int n ; }

int new
// constructor
kdtree ( point p [ ] , n) : tree ( point [ n ] ) , n
double
// priority queue for KNN, keep the K nearest
(n) { p r i o r i t y _ q u e u e <p a i r < , p o i n t ∗> > pq ;
copy ( p , p + n , t r e e ) ; void perform_query ( double double x, y, int k,
build (0 , n , false
); int L, int bool
R, dvx ) {
} if (L >= R) return ;
int M = (L + R) / 2 ;
delete [ ] double
// destructor
~kdtree () { tree ;} dx = x − t r e e [M] . x ;
double dy = y − t r e e [M] . y ;
CAPÍTULO 2. ESTRUTURAS DE DADOS 15

double d e l t a = dvx ? dx : dy ; swap ( nearL , f a r L ) ;


double d i s t = dx ∗ dx + dy ∗ dy ; swap ( nearR , farR ) ;
// if point is nearer to the kth farthest , }

if
put point in queue // query the nearer child
( pq . s i z e ( ) < k | | d i s t < pq . top ( ) . f i r s t ) perform_query ( x , y , k , nearL , nearR , ! dvx ) ;
{
pq . push ( make_pair ( d i s t , &t r e e [M] ) ) ; if ( pq . s i z e ( ) < k | | d e l t a ∗ d e l t a < pq . top
if ( pq . s i z e ( ) > k ) pq . pop ( ) ; // k e e p k () . f i r s t )
elements only // query the farther child if there might be
}
int nearL = L ,
candidates
nearR = M, f a r L = M + 1 , farR perform_query ( x , y , k , farL , farR , ! dvx ) ;
= R; }
if ( d e l t a > 0 ) { // right is nearer };

2.12 Treap / Cartesian Tree


Suporta operações da BST, mais importante lessOrEqualT hanK().

else i n s e r t ( i t , i t −>key < t −>key ? t −>l : t


template <class T> −>r ) ;
class Treap { updateNode ( t ) ;
private : }
struct node { void e r a s e (T key , pnode &t ) {
T key ; if ( ! t ) return ;
int p r i o r ; if ( t−>key == key ) merge ( t , t−>l , t−>r ) ;
int s i z e ; else e r a s e ( key , key < t−>key ? t−>l : t−>r ) ;
node ∗ l , ∗ r ; updateNode ( t ) ;
node ( ) { } ; }
node (T key , int p r i o r ) : key ( key ) , p r i o r ( void preOrder ( pnode t) {
p r i o r ) , s i z e ( 1 ) , l (NULL) , r (NULL) {} if ( ! t ) return ;
node (T key ) : key ( key ) , p r i o r ( rand ( ) ) , s i z e preOrder ( t −>l ) ;
( 1 ) , l (NULL) , r (NULL) {} c o u t << t −>key << e n d l ;
}; preOrder ( t −>r ) ;
typedef node ∗ pnode ; }
int lessOrEqualThanK (T key , pnode t ) {
int g e t S i z e ( pnode p ) { return p ? p−>s i z e : 0 ; if ( ! t ) return 0 ;
} if ( t−>key <= key ) return g e t S i z e ( t−>l ) + 1 +
void updateNode ( pnode p ) { lessOrEqualThanK ( key , t −>r ) ;
if ( p ) { else return lessOrEqualThanK ( key , t−>l ) ;
p−>s i z e = g e t S i z e ( p−>l ) + g e t S i z e ( p−>r ) + }
1; public :
} pnode r o o t ;
} Treap ( ) {
void s p l i t ( pnode t , T key , pnode &l , pnode &r ) r o o t = NULL;
{ s r a n d ( time (NULL) ) ;
if ( ! t ) l = r = NULL; };
else if ( key < t−>key ) s p l i t ( t−>l , key , l , void i n s e r t (T key ) { i n s e r t ( new
node ( key ) , r o o t
t −>l ) , r = t ; ); }
else s p l i t ( t−>r , key , t−>r , r ) , l = t ; void e r a s e (T key ) { e r a s e ( key , r o o t ) ; }
updateNode ( t ) ; void preOrder ( ) { preOrder ( r o o t ) ; }
} int lessOrEqualThanK (T key ) { return
void merge ( pnode &t , pnode l , pnode r ) { lessOrEqualThanK ( key , r o o t ) ; }
if ( ! l | | ! r ) t = l ? l : r ; int getQtdInRange (T l e f t , T r i g h t ) { return
else if ( l −>p r i o r > r−>p r i o r ) merge ( l −>r , l −> lessOrEqualThanK ( r i g h t , r o o t ) −
r , r) , t = l ; lessOrEqualThanK ( l e f t − 1 , r o o t ) ; }
else merge ( r−>l , l , r−>l ) , t = r ; int getSizeTree () { return getSize ( root ) ; }
updateNode ( t ) ; };
}
void i n s e r t ( pnode i t , pnode &t ) {
if ( ! t ) t = i t ; int >
// Declaracaoo
Treap< tr ;
else if ( i t −>p r i o r > t−>p r i o r ) s p l i t ( t , i t −>
key , i t −>l , i t −>r ) , t = i t ;

2.13 Treap / Cartesian Tree Implícita


Implicit cartesian tree O(logn).
CAPÍTULO 2. ESTRUTURAS DE DADOS 16

do
// Prior e size obrigatorios
t += i n f o r m a c a o no a t u a l
struct
// Carregar o que precisa
node { }
int prior , size , lazy ;
int val ; void s p l i t ( node ∗ t , node ∗&l , node ∗&r , int pos ,
int add = 0 ) {
node ∗ l , ∗ r ; if ( ! t ) {
node ( ) {} l = r = NULL;
node ( intn){ return ;
p r i o r = rand ( ) ; }
size = 1;
val = n ; lazy ( t ) ;
lazy = 0; int cur_pos = add + s i z e ( t −>l ) ;
l = r = NULL; if ( cur_pos <= pos )
} s p l i t ( t −>r , t −>r , r , pos , cur_pos + 1 ) , l =
}; t;
else
int s i z e ( node ∗ t ) { s p l i t ( t −>l , l , t −>l , pos , add ) , r = t ;
return t ? t −>s i z e : 0 ; updateSize ( t ) ;
} operation ( t ) ;
}
void u p d a t e S i z e ( node ∗t ){
if ( t ) void merge ( node ∗&t , node ∗ l , node ∗ r ) {
t −>s i z e = 1 + s i z e ( t −>l ) + s i z e ( t −>r ) ; lazy ( l ) ;
} lazy ( r ) ;
if(! l || ! r)
t = l ? l : r;
void l a z y ( node ∗ t ) { else if
// Lazy para inverter intervalo
( l −>p r i o r > r −>p r i o r )
if ( ! t | | ! t−>l a z y ) merge ( l −>r , l −>r , r ) , t = l ;
return ; else
merge ( r −>l , l , r −>l ) , t = r ;
t −>l a z y = t −>l a z y % 2 ; updateSize ( t ) ;
if ( t −>l a z y ) { operation ( t ) ;
swap ( t −>r , t −>l ) ; }
if ( t −>l )
t −>l −>l a z y ++;
if void int int
// Inverte o range l .. r
( t −>r ) i n v e r t e r ( node ∗ t , l, r ){
t −>r −>l a z y ++; node ∗ L , ∗ mid , ∗R;
} s p l i t ( t , L , mid , l − 1 ) ;
t −>l a z y = 0 ; s p l i t ( mid , t , R, r − l ) ;
} t −>l a z y ++;
merge ( mid , L , t ) ;
merge ( t , mid , R) ;
void o p e r a t i o n ( node
// Operator +
∗t ){ }
if ( ! t )
return ; // Criacao da Treap na main
l a z y ( t −>l ) ; node ∗ Treap ;
l a z y ( t −>r ) ; for int
( i = 0 ; i < n ; i ++){
if(! i )
Treap = new
node ( v [ i ] ) ;
if ( t−>l ) else
t += j u n c a o com f i l h o e s q u e r d a merge ( Treap , Treap , new node ( v [ i ] ) ) ;
if ( t−>r ) }
t += j u n c a o com f i l h o d i r e i t a

2.14 Sparse table


Suporta min, max, gcd, lcm, build em O(nlogn) e query em O(1).

#define MAXN 100100 s t [ i ] [ j ] = min ( s t [ i ] [ j − 1 ] , s t [ i + ( 1 <<


#define LOG 17 // ~ l o g 2 (MAXN) ( j − 1) ) ] [ j − 1 ] ) ;
}
int a r r [MAXN] , s t [MAXN] [ LOG ] ;
int query ( int l, int r ){
void b u i l d ( int n ) {
for ( int i = 0 ; i < n ; i ++)
// Pre processar os logs ou usar __builtin_ctz

int k = f l o o r ( l o g 2 ( ( double ) r − l + 1 ) ) ;
se o tempo estiver apertado
st [ i ] [ 0 ] = arr [ i ] ;
return min ( s t [ l ] [ k ] , s t [ r − ( 1 << k ) + 1 ] [ k ] ) ;
for ( int j = 1 ; ( 1 << j ) <= n ; j ++) }
for ( int i = 0 ; i + ( 1 << j ) − 1 < n ; i ++)
CAPÍTULO 2. ESTRUTURAS DE DADOS 17

2.15 Persistent Segment Tree


Persistent aplicada para encontrar o menor elemento que não pode ser formado através da soma de elementos de um
subarray.

}
struct node {
node ∗ l , ∗ r ; l l g e t ( node ∗ cur , intl, int
r, int
x, y){ int
l l sum ; if ( l > y | | r < x)
node ( ) { return 0;
l = r = 0; if ( l >= x && r <= y )
sum = 0 ; return cur −>sum ;
} return g e t ( cur −>l , l , ( l+r ) / 2 , x , y ) + g e t ( cur
}; −>r , ( l+r ) /2+1 , r , x , y ) ;
}
i i v [MAXN] ;
node ∗ r o o t s [MAXN] ; int
l l get ( l, int r ){
int n, q; l l s = 0;
while (1) {
void update ( node ∗ l a s t , node ∗ cur , int l, int r, l l c u r = g e t ( r o o t s [ upper_bound ( v , v+n , i i ( s
int pos , int v a l ) { +1, n+1) ) − v ] , 1 , n , l , r ) ;
if ( l > pos | | r < pos ) if ( c u r == s )
return ; return s +1;
if ( l == r && r == pos ) { s = cur ;
cur −>sum = l a s t −>sum + v a l ; }
return ; return 0;
} }

int mid = ( l+r ) / 2 ; void s o l v e ( ) {


if ( pos <= mid ) { s c a n f ( "%d %d" , &n , &q ) ;
cur −>l = new node ( ) ; for ( int i = 0 ; i < n ; i ++){
cur −>r = l a s t −>r ; s c a n f ( "%d" , &v [ i ] . f s t ) ;
update ( l a s t −>l , cur −>l , l , ( l+r ) / 2 , pos , v a l v [ i ] . snd = i ;
); }
}
else { s o r t ( v , v+n ) ;
cur −>r = newnode ( ) ;
cur −>l = l a s t −>l ; roots [ 0 ] = new node ( ) ;
update ( l a s t −>r , cur −>r , ( l+r ) /2+1 , r , pos , build ( roots [ 0 ] , 1 , n) ;
val ) ; for int
( i = 1 ; i <= n ; i ++){
} roots [ i ] = newnode ( ) ;
cur −>sum = cur −>l −>sum + cur −>r −>sum ; update ( r o o t s [ i − 1] , r o o t s [ i ] , 1 , n , v [ i − 1 ] .
} snd +1, v [ i − 1 ] . f s t ) ;
}
void b u i l d ( node ∗ cur , int l, int r ){
if ( l == r ) int l , r ;
return ; while ( q−−){
cur −>l = new node ( ) ; s c a n f ( "%d %d" , &l , &r ) ;
cur −>r = new node ( ) ; p r i n t f ( "%l l d \n" , g e t ( l , r ) ) ;
b u i l d ( cur −>l , l , ( l+r ) / 2 ) ; }
b u i l d ( cur −>r , ( l+r ) /2+1 , r ) ; }

2.16 Wavelet Tree


K-ésimo menor elemento de um range, número de ocorrências de X no em um range, número de elementos em um range
que são menores que ou iguais a X e soma dos elementos menores que X em um range O(logn).

if ( l o == h i or from >= to ) return ;


struct wavelet_tree { int mid = ( l o+h i ) / 2 ;
#d e f i n e v i v e c t o r < > int auto f = [ mid ] ( int x ) {
#d e f i n e pb push_back return x <= mid ;
int lo , hi ; };
wavelet_tree ∗ l , ∗ r ; b . r e s e r v e ( to −from +1) ;
vi b ; b . pb ( 0 ) ;
for auto
( i t = from ; i t != t o ; i t ++)
// n o s are in range [x,y] b . pb ( b . back ( ) + f ( ∗ i t ) ) ;

int int int int auto p i v o t = s t a b l e _ p a r t i t i o n ( from , to , f ) ;


// a r r a y indices are [ from , to ) // s e e how lambda function is used here
wavelet_tree ( ∗ from , ∗ to , x, y){
lo = x , hi = y ; l = new w a v e l e t _ t r e e ( from , p i v o t , l o , mid ) ;
CAPÍTULO 2. ESTRUTURAS DE DADOS 18

r = new w a v e l e t _ t r e e ( p i v o t , to , mid+1, h i ) ; if ( l o == h i ) return r − l + 1 ;


} int l b = b [ l − 1] , rb = b [ r ] , mid = ( l o+h i ) / 2 ;
if ( k <= mid ) return this −>l −>count ( l b +1, rb ,
k) ;
int int int int return this −>r−>count ( l −lb , r−rb , k ) ;
// k t h smallest element in [ l , r]
kth ( l, r, k){
if(l > r) return 0; }
if( l o == h i ) return lo ;
int inLeft = b [ r ] − b [ l −1];
int int int int int
//sum of nos in [ l ,r] less than or equal to k
l b = b [ l − 1 ] ; // amt o f n o s sumk ( l, r, k) {
if or return
− in first (l 1)
(l > r k < lo ) 0;
int rb = b [ r ] ; if return
nos that go in left
( h i <= k ) c [ r ] − c [ l −1];
int
// amt of nos in first (r) nos
l b = b [ l − 1] , rb = b [ r ] ;
if ( k <= i n L e f t ) return this −>l −>kth ( l b +1, rb return this this −>r
that go in left
−>l −>sumk ( l b +1, rb , k ) +
, k) ; −>sumk ( l −lb , r −rb , k ) ;
return this −>r−>kth ( l −lb , r−rb , k−i n L e f t ) ; }
}
~wavelet_tree ( ) {
delete
l;
delete
// c o u n t of nos in [ l , r] Less than or equal to
r;
int LTE( int l , int r , int k ) {
k
}
if ( l > r or k < l o ) return 0 ; };
if ( h i <= k ) return r − l + 1 ;
int l b = b [ l − 1] , rb = b [ r ] ;
return this −>l −>LTE( l b +1, rb , this −>r−>
// Main
k) + s r a n d ( time (NULL) ) ;
LTE( l −lb , r −rb , k ) ; int a [ n ] ; // V a l o r e s
} w a v e l e t _ t r e e T( a , a+n , 1 , MAX) ;
T. kth ( l , r , k )
T. LTE( l , r , k )
int int l , int r , int k ) {
// c o u n t of nos in [ l , r] equal to k
count ( T. count ( l , r , k )
if(l > r or k < l o or k > h i ) return 0;
Capítulo 3

Paradigmas
3.1 Convex hull trick 1
Quando o X está ordenado.
Inserir retas do tipo Y = A*X + B.
Para máximo adicionar o A e B negativos e quando consultar coloca negativo o valor.

struct hull { A[ l e n ] = a ;
l l A[MAXN] ; B[ len ] = b ;
l l B [MAXN] ; l e n ++;
int len , ptr ; }
hull () {
len = ptr = 0; l l get ( l l x) {
} p t r = min ( ptr , l e n − 1) ;
while ( p t r+1 < l e n && A[ p t r +1] ∗ x+B [ p t r +1] <=
void addLine ( l l a , l l b ) { A[ p t r ] ∗ x + B [ p t r ] )
while ( l e n >= 2 && (B [ l e n − 2] − B [ l e n − 1]) ∗ (a p t r ++;
−A[ l e n − 1]) >= (B [ l e n −1]− b ) ∗ (A[ l e n −1]−A return A[ p t r ] ∗ x + B [ p t r ] ;
[ l e n − 2]) ) }
l e n −−; };

3.2 Convex hull trick 2


Quando o X não está ordenado.

class ConvexHullTrick { p i l h a . pop_back ( ) ;


struct CHTPoint { tam−−;
double x , y , l i m ; }
}; while ( tam >= 1 && f a b s ( p i l h a [ tam − 1 ] . x − a )
v e c t o r <CHTPoint> p i l h a ; < 1 e − 8) {
inline double g e t _ i n t e r s e c t i o n ( CHTPoint a , p i l h a . pop_back ( ) ;
CHTPoint b ) { tam−−;
double denom = ( double (b . x) − a . x) ; }
double num = ( double (b . y) − a . y) ;
p i l h a . push_back ( novo ) ;
return −num / denom ; if ( tam >= 1 ) p i l h a [ tam − 1 ] . l i m =
} g e t _ i n t e r s e c t i o n ( p i l h a [ tam − 1] , p i l h a [ tam
]) ;
bool ccw ( CHTPoint p0 , CHTPoint p1 , CHTPoint p2 ) }
{
return ( ( double ) ( p1 . y−p0 . y ) ∗ ( double ) ( p2 . x−p0 double get_maximum ( double x ) {
. x ) > ( double ) ( p2 . y−p0 . y ) ∗ ( double ) ( p1 . x− int s t = 0 , ed = p i l h a . s i z e ( ) − 1 ;
p0 . x ) ) ; while ( s t < ed ) {
} int mid = ( s t+ed ) / 2 ;
if ( p i l h a [ mid ] . l i m < x ) s t = mid+1;
public : else ed = mid ;
}
void add_line ( double a , double b ) { return p i l h a [ s t ] . x ∗ x + p i l h a [ s t ] . y ;
CHTPoint novo = {a , b , 0 } ; }
int tam = p i l h a . s i z e ( ) ;
while ( tam >= 2 && ! ccw ( p i l h a [ tam − 2] , pilha [ };
tam − 1] , novo ) ) {
19
CAPÍTULO 3. PARADIGMAS 20

3.3 Convex hull trick 3 - Fully Dynamic


Sem condições especiais para o A e B

const l l is _ q ue r y = −(1LL<<62) ; if ( z == end ( ) ) return y−>m == x−>m && y−>b


struct Line { <= x−>b ;
l l m, b ; return ( x−>b − y−>b ) ∗ ( z−>m − y−>m) >= ( y−>b
mutable f u n c t i o n <const Line ∗ ( )> s u c c ; − z−>b ) ∗ ( y−>m − x−>m) ;
bool operator <( const Line& r h s ) const { }
if ( r h s . b != i s _ q ue r y ) return m < r h s .m; void i n s e r t _ l i n e ( l l m, l l b ) {
const Line ∗ s = s u c c ( ) ; auto y = i n s e r t ( { m, b } ) ;
if ( ! s ) return 0 ; y−>s u c c = [ = ] { return next ( y ) == end ( ) ? 0
l l x = r h s .m; : &∗ next ( y ) ; } ;
return b − s−>b < ( s−>m − m) ∗ x ; if ( bad ( y ) ) { e r a s e ( y ) ; return ; }
} while ( next ( y ) != end ( ) && bad ( next ( y ) ) )
}; e r a s e ( next ( y ) ) ;
while ( y != b e g i n ( ) && bad ( prev ( y ) ) ) e r a s e (
struct HullDynamic : public m u l t i s e t <Line> { // prev ( y ) ) ;
}
bool bad ( i t e r a t o r y ) {
will maintain upper hull for maximum
l l eval ( l l x) {
auto z = next ( y ) ; auto l = ∗ lower_bound ( ( Line ) { x , i s_ q u e ry
if ( y == b e g i n ( ) ) { }) ;
if ( z == end ( ) ) return 0 ; return l .m ∗ x + l . b ;
return y−>m == z−>m && y−>b <= z−>b ; }
} };
auto x = prev ( y ) ;

3.4 Divide and conquer optimization


Dividir elementos em K pilhas sai de O(KN 2 ) para O(KN logN ).

void s o l v e ( int i , int l e f t , int r i g h t , int k l e f t , bestk = k ;


int k r i g h t ) { }
if ( l e f t > r i g h t ) }
return ;
s o l v e ( i , l e f t , jmid − 1, k l e f t , b e s t k ) ;
int jmid = ( r i g h t+ l e f t ) / 2 ; s o l v e ( i , jmid +1, r i g h t , bestk , k r i g h t ) ;
dp [ i ] [ jmid ] = 1<<30; }
int b e s t k = −1;
for ( int k = k l e f t ; k <= min ( k r i g h t , jmid ) ; k++)
for ( int i = 1 ; i <= n ; i ++)
// Chamada fica assim
{
if ( dp [ i − 1 ] [ k ] + g e t ( k+1, jmid ) < dp [ i ] [ jmid
// Casos base
dp [ 1 ] [ i ] = g e t ( 1 , i ) ;
]){
dp [ i ] [ jmid ] = dp [ i − 1 ] [ k ] + g e t ( k+1, jmid ) for ( int i = 2 ; i <= k ; i ++)
; // Cost function solve ( i , 1 , n , 1 , n) ;

3.5 Knuth optimization


Dividir elementos P elementos em A pilhas.

for ( int i = 0 ; i <= p + 1 ; i ++) dp [ i ] [ j ] = 1LL << 6 1 ;


for ( int j = 0 ; j <= a + 1 ; j ++) for int
( x = dpAux [ i ] [ j − 1 ] ; x <= dpAux [ i +
dpAux [ i ] [ j ] = 1 ; 1 ] [ j ] ; x++){
if ( dp [ i ] [ j ] >= dp [ x ] [ j − 1 ] + g e t ( x + 1 ,
for ( int i = 1 ; i <= p ; i ++) i ) ∗ ( i − x) ){
dp [ i ] [ 1 ] = p r e f i x [ i ] ∗ i ; dp [ i ] [ j ] = dp [ x ] [ j − 1 ] + g e t ( x + 1 , i
) ∗ ( i − x) ;
for ( int i = 0 ; i <= a ; i ++) dpAux [ i ] [ j ] = x ;
dpAux [ p + 1 ] [ i ] = p ; }
}
for ( int j = 2 ; j <= a ; j ++) }
for ( int i = p ; i >= 1 ; i −−){
CAPÍTULO 3. PARADIGMAS 21

3.6 Otimização com bitmask


dp[i] é igual a um bitmask onde o i-ésimo bit informa se é possível fazer a soma i usando x elementos, onde x é a posição
do bitmask.

dp [ 0 ] = 1 ; l l y = 1LL<<(n/2+1) ;
for int
( i = 0 ; i < n ; i ++) while ( ! ( dp [ ans ]&x )
&& ! ( dp [ ans ]&y ) )
for int
( j = sum / 2 ; j >= v [ i ] ; j −−) ans −−;
dp [ j ] |= dp [ j −v [ i ]]<<1LL ; }
else
int ans = sum / 2 ; while ( ! ( dp [ ans ]&(1LL<<(n / 2 ) ) ) )
if ( n&1){ ans −−;
l l x = 1LL<<(n / 2 ) ;
Capítulo 4

Grafos
4.1 Ford Fulkerson
Encontra o uxo máximo em O(|f*|E).

#define MAXN 100000 for ( auto e : graph [ s ] ) {


struct node { if ( v i s [ e d g e s [ e ] . v ] < c n t && e d g e s [ e ] . c−e d g e s
int v , f , c ; [ e ] . f > 0) {
node ( ) {} if ( int x = d f s ( e d g e s [ e ] . v , t , min ( f , e d g e s
node ( int _v , int _f , _c) { int [ e ] . c− e d g e s [ e ] . f ) ) ) {
v = _v , f = _f , c = _c ; e d g e s [ e ] . f += x ;
} e d g e s [ e ^ 1 ] . f −= x ;
}; return x;
}
v e c t o r <node> e d g e s ; }
vector< int > graph [MAXN] ; }
int v i s [MAXN] ; return 0;
int cnt ; }

void add ( int u, int v, int c){ int maxFlow ( int


s, int
t ){
e d g e s . pb ( node ( v , 0 , c ) ) ; int ans = 0 ;
graph [ u ] . pb ( e d g e s . s i z e ( ) −1) ; cnt = 1 ;
e d g e s . pb ( node ( u , 0 , 0 ) ) ; memset ( v i s , 0 , sizeof
vis ) ;
graph [ v ] . pb ( e d g e s . s i z e ( ) −1) ; while int
( f l o w = d f s ( s , t , 1<<30) ) {
} ans += f l o w ;
c n t++;
int d f s ( int s , int t, int f ){ }
if ( s == t ) return ans ;
return f ; }
v i s [ s ] = cnt ;

4.2 Edmonds Karp


Troca a df s() do Ford Fulkerson por uma bf s() e o uxo máximo ca em O(V E 2 ).

4.3 Dinic
Encontra o uxo máximo em O(V 2 E).

#define MAXN 5050 v e c t o r <int > graph [MAXN] ;


#define i n f 0 x 3 f 3 f 3 f 3 f int d i s t [MAXN] ;
int p t r [MAXN] ;
struct node {
int v , f , c ; void add ( int u , int v , int c){
node ( ) {} e d g e s . pb ( node ( v , 0 , c ) ) ;
node ( int _v , int _f , int _c) { graph [ u ] . pb ( e d g e s . s i z e ( ) −1) ;
v = _v , f = _f , c = _c ; e d g e s . pb ( node ( u , 0 , 0 ) ) ;
} graph [ v ] . pb ( e d g e s . s i z e ( ) −1) ;
}; }
v e c t o r <node> e d g e s ;

22
CAPÍTULO 4. GRAFOS 23

bool bfs ( int s, intt ){ int e = graph [ s ] [ i ] ;


memset ( d i s t , i n f , sizeof dist ) ; if ( d i s t [ e d g e s [ e ] . v ] == d i s t [ s ]+1 && e d g e s [ e
dist [ s ] = 0; ] . c− e d g e s [ e ] . f > 0 ) {
queue< int> q; if ( int x = d f s ( e d g e s [ e ] . v , t , min ( f ,
q . push ( s ) ; e d g e s [ e ] . c− e d g e s [ e ] . f ) ) ) {
e d g e s [ e ] . f += x ;
while ( ! q . empty ( ) ) { e d g e s [ e ^ 1 ] . f −= x ;
int u = q . f r o n t ( ) ; q . pop ( ) ; return x;
for ( auto e : graph [ u ] ) { }
if ( d i s t [ e d g e s [ e ] . v ] == i n f && e d g e s [ e ] . c− }
edges [ e ] . f > 0) { }
q . push ( e d g e s [ e ] . v ) ;
d i s t [ edges [ e ] . v ] = d i s t [ u ] + 1; return 0;
} }
}
} int maxFlow ( int s , int t ) {
int ans = 0 ;
return d i s t [ t ] != i n f ; while ( b f s ( s , t ) ) {
} memset ( ptr , 0 , sizeof p t r ) ;
while ( int f = d f s ( s , t , i n f ) )
int d f s ( int s , int t , int f ){ ans += f ;
if ( s == t ) }
return f ; return ans ;
for ( int &i = p t r [ s ] ; i < graph [ s ] . s i z e ( ) ; i ++){ }

4.4 Min cost max ow


Máximo uxo com custo mínimo.

#define MAXN 1100 if ( d > d i s t [ u ] )


#define i n f 0 x 3 f 3 f 3 f 3 f continue ;
struct node {
int v , f , c , v a l ; for ( auto e : graph [ u ] ) {
node ( ) {} if ( d i s t [ u ] + e d g e s [ e ] . v a l < d i s t [ edges [ e
node ( int _v , int _f , int _c , _val ) { int ] . v ] && e d g e s [ e ] . c−e d g e s [ e ] . f > 0 ) {
v = _v , f = _f , c = _c , v a l = _val ; d i s t [ edges [ e ] . v ] = d i s t [ u ] + edges [ e ] .
} val ;
}; pai [ edges [ e ] . v ] = u ;
q . push ( { d i s t [ e d g e s [ e ] . v ] , e d g e s [ e ] . v } )
int v; ;
v e c t o r <node> e d g e s ; }
vector< int> graph [MAXN] ; }
int d i s t [MAXN] , p t r [MAXN] , p a i [MAXN] ; }

void add ( int u, int v, int c, int


val ){ return d i s t [ t ] != i n f ;
e d g e s . pb ( node ( v , 0 , c , v a l ) ) ; }
graph [ u ] . pb ( e d g e s . s i z e ( ) −1) ;
e d g e s . pb ( node ( u , 0 , 0 , − v a l ) ) ; i i dfs ( int int t , int f ) {
s,
graph [ v ] . pb ( e d g e s . s i z e ( ) −1) ; if
( s == t )
} return i i ( 0 , f ) ;
ii operator +( i i a , i i b ) { for ( int &i = p t r [ s ] ; i < graph [ s ] . s i z e ( ) ; i ++){
a . f s t += b . f s t ; int e = graph [ s ] [ i ] ;
a . snd += b . snd ; if ( p a i [ e d g e s [ e ] . v ] == s && d i s t [ e d g e s [ e ] . v ]
return a; == d i s t [ s ] + e d g e s [ e ] . v a l && e d g e s [ e ] . c−
} edges [ e ] . f > 0) {
i i x = i i ( e d g e s [ e ] . val , 0 ) + d f s ( e d g e s [ e
bool d i j k s t r a ( int s, int
t ){ ] . v , t , min ( f , e d g e s [ e ] . c−e d g e s [ e ] . f )
for ( int i = 0 ; i < v ; i ++){ );
dist [ i ] = inf ; if ( x . snd ) {
p a i [ i ] = − 1; e d g e s [ e ] . f += x . snd ;
} e d g e s [ e ^ 1 ] . f −= x . snd ;
dist [ s ] = 0; return x;
p r i o r i t y _ q u e u e <i i , v e c t o r <i i >, g r e a t e r <i i >> q ; }
q . push ( i i ( 0 , s ) ) ; }
}
while ( ! q . empty ( ) ) {
int d = q . top ( ) . f s t , u = q . top ( ) . snd ; return i i (0 , 0) ;
q . pop ( ) ; }
CAPÍTULO 4. GRAFOS 24

while ( ( x = d f s ( s , t , i n f ) ) . snd )
int
i i get ( s, int
t ){ ans = ans + x ;
i i ans ( 0 , 0 ) ; }
while ( dijkstra (s , t ) ){ return ans ;
memset ( ptr , 0 , sizeof ptr ) ; }
ii x;

4.5 Stoer-Wagner
Custo mínimo para quebrar o grafo em dois componentes.

{
#define NN 105 int z j = −1;
#define MAXW 105 for ( int j = 1 ;
// Vertices
j < n ; j ++)
if ( ! a [ v [ j ] ] &&
// Max value of edge
( z j < 0 | | w [ j ] > w[ z j ] ) )
int g [NN ] [ NN] , v [NN] , w[NN] , na [NN ] ; // g r a p h zj = j ;

bool a [NN ] ; true ;


comeca com tudo 0
a [ v [ zj ] ] =

int minCut ( int n ) if ( i == n − 1 )


{ {
for ( int i = 0 ; i < n ; i ++) b e s t = min ( b e s t , w [ z j ] ) ;
v[ i ] = i ; for ( int j = 0 ; j < n ; j ++)
g [ v [ j ] ] [ prev ] = g [ prev ] [ v [ j ] ] += g [ v [
int b e s t = MAXW ∗ n ∗ n ; zj ] ] [ v [ j ] ] ;
while ( n > 1 ) v [ z j ] = v[−−n ] ;
{ break ;
a [ v [ 0 ] ] = true ; }
for ( int i = 1 ; i < n ; i ++) prev = v [ z j ] ;
{
a [ v [ i ] ] = false ; for ( int j = 1 ; j < n ; j++ )
na [ i − 1 ] = i ; if ( ! a [ v [ j ] ] )
w[ i ] = g [ v [ 0 ] ] [ v [ i ] ] ; w[ j ] += g [ v [ z j ] ] [ v [ j ] ] ;
} }
}
int prev = v [ 0 ] ; return best ;
for ( int i = 1 ; i < n ; i ++) }

4.6 Tarjan
Componentes fortemente conexos em O(V + E).

#define MAXN 100100 s c c s ++;


v e c t o r <int > graph [MAXN] ; int x;
s t a c k <int > s t ; do{
int i n [MAXN] , low [MAXN] , v i s [MAXN] , c n t ; x = s t . top ( ) ;
int s c c s ; s t . pop ( ) ;
i n [ x ] = 1<<30;
void d f s ( int u ) { } while ( x != u ) ;
i n [ u ] = low [ u ] = c n t++; }
vis [ u ] = 1; }
s t . push ( u ) ;
void tarjan ( int n){
for ( auto v : graph [ u ] ) { cnt = s c c s = 0 ;
if ( ! v i s [ v ] ) { memset ( v i s , 0 , sizeof
vis ) ;
dfs (v) ; while ( ! s t . empty ( ) )
low [ u ] = min ( low [ u ] , low [ v ] ) ; s t . pop ( ) ;
} for int
( i = 0 ; i < n ; i ++)
else if (! vis [ i ])
low [ u ] = min ( low [ u ] , i n [ v ] ) ; dfs ( i ) ;
} }
if ( low [ u ] == i n [ u ] ) {

4.7 Pontos de articulação


Complexidade O(V + E).
CAPÍTULO 4. GRAFOS 25

#define MAXN 100100 }


v e c t o r <int > graph [MAXN] ; else if ( v != p )
int i n [MAXN] , low [MAXN] , v i s [MAXN] , cnt ; low [ u ] = min ( low [ u ] , i n [ v ] ) ;
v e c t o r <int > p o i n t s ;
}
void d f s ( int u , int p , int r o o t ) { if ( u == r o o t && t o t a l >= 2 | | ok && u != r o o t )
i n [ u ] = low [ u ] = c n t++; p o i n t s . pb ( u ) ;
vis [ u ] = 1; }
int total = 0;
bool ok = 0 ; void getPoints ( int
n){
for auto
( v : graph [ u ] ) { cnt = 0 ;
if (! vis [ v ]) { points . clear () ;
dfs (v , u , root ) ; memset ( v i s , 0 , sizeof
vis ) ;
low [ u ] = min ( low [ u ] , low [ v ] ) ; for int
( i = 0 ; i < n ; i ++)
t o t a l ++; if(! vis [ i ])
if ( low [ v ] >= i n [ u ] ) dfs ( i , i ) ;
ok = 1 ; }
// i f ( low [ v ] > in [ u ] ) u−v eh uma ponte

4.8 LCA (Sparce Table)


Complexidade < O(nlog), O(log) >.

#define INF 0 x 3 f 3 f 3 f 3 f int lca ( intu, int


v){
#define N 1100 if ( depth [ u ] > depth [ v ] )
#define LOG 15 swap ( u , v ) ;

int p a r e n t s [N ] [ LOG] , depth [N ] ; for ( int i = LOG − 1 ; i >= 0 ; i −−)


v e c t o r <vi > graph ; if ( p a r e n t s [ v ] [ i ] != −1 && depth [ p a r e n t s [ v ] [ i ] ]
>= depth [ u ] )
void dfs ( int u, int
p, int h){ v = parents [ v ] [ i ] ;
parents [ u ] [ 0 ] = p ;
depth [ u ] = h ; if ( u == v )
return u ;
for ( int i = 1 ; i < LOG; i ++)
if ( p a r e n t s [ u ] [ i − 1 ] != −1) for ( int i = LOG − 1 ; i >= 0 ; i −−)
parents [ u ] [ i ] = parents [ parents [ u ] [ i − 1 ] ] [ i − if ( p a r e n t s [ u ] [ i ] != p a r e n t s [ v ] [ i ] ) {
1]; u = parents [ u ] [ i ] ;
v = parents [ v ] [ i ] ;
for ( int i = 0 ; i < graph [ u ] . s i z e ( ) ; i ++) }
if ( graph [ u ] [ i ] != p a r e n t s [ u ] [ 0 ] )
d f s ( graph [ u ] [ i ] , u , h + 1 ) ; return parents [ u ] [ 0 ] ;
} }

4.9 Posição de elemento em K passos em um ciclo


Encontra onde estará um elemento após executar K passos dentro de um ciclo O(nlogn)

#define N 100000 for ( int i = 1 ; i < LOG; i ++)


#define LOG 31 for ( int j = 0 ; j < n ; j ++)
int dp [N ] [ LOG ] ; dp [ j ] [ i ] = dp [ dp [ j ] [ i − 1 ] ] [ i − 1 ] ;

for ( int j = 0 ; j < LOG; j ++)


for ( int if ( k&(1<< j ) )
// Caso base
i = 0 ; i < n ; i ++)
dp [ i ] [ 0 ] = l i g a c a o [ i ] ; u = dp [ u ] [ j ] ;

4.10 Hopcroft Karp


Maior matching em grafo bipartido. O(E ∗ sqrt(V ))

#define MAXN 100100


v e c t o r <int > graph [MAXN] ; bool bfs () {
int d i s t [MAXN] , match [MAXN] ; queue< int
> q;
CAPÍTULO 4. GRAFOS 26

for ( int i = 1 ; i <= n ; i ++){ for ( auto v : graph [ u ] ) {


if ( ! match [ i ] ) { if ( d i s t [ match [ v ] ] == d i s t [ u ]+1) {
dist [ i ] = 0; if ( d f s ( match [ v ] ) ) {
q . push ( i ) ; match [ v ] = u ;
} match [ u ] = v ;
else return 1;
d i s t [ i ] = 1<<30; }
} }
}
d i s t [ 0 ] = 1<<30; d i s t [ u ] = 1<<30;
while ( ! q . empty ( ) ) { return 0;
int u = q . f r o n t ( ) ; q . pop ( ) ; }
if ( u ) { return 1 ;
for ( auto v : graph [ u ] ) }
if ( d i s t [ match [ v ] ] == 1<<30){
int
// Grafo indexado de 1
d i s t [ match [ v ] ] = d i s t [ u ] + 1 ; hopcroftKarp ( ) {
q . push ( match [ v ] ) ; int ans = 0 ;
} memset ( match , 0 , sizeof
match ) ;
} while( bfs () )
} for int
( i = 1 ; i <= n ; i ++)
return d i s t [ 0 ] != 1<<30; if ( ! match [ i ] && d f s ( i ) )
} ans++;
return ans ;
bool d f s ( int u){ }
if ( u ) {

4.11 Blossom
Matching para grafos genéricos.

q [ qt++] = r o o t ;
int l c a ( v i &match , v i &base , v i &p , int a, int b){ while ( qh < qt ) {
v i used ( match . s i z e ( ) , 0 ) ; int v = q [ qh++];
while (1) { for int
( t o : graph [ v ] ) {
a = base [ a ] ; if ( b a s e [ v ] == b a s e [ t o ] | | match [ v ] == t o )
used [ a ] = 1 ; continue ;
if ( match [ a ] == −1) if ( t o == r o o t | | match [ t o ] != −1 && p [
break ; match [ t o ] ] != −1) {
a = p [ match [ a ] ] ; int c u r b a s e = l c a ( match , base , p , v ,
} to ) ;
while (1) { v i blossom ( n , 0 ) ;
b = base [ b ] ; markPath ( match , base , blossom , p , v ,
if ( used [ b ] ) curbase , to ) ;
return b; markPath ( match , base , blossom , p , to ,
b = p [ match [ b ] ] ; curbase , v ) ;
}
} for ( int i = 0 ; i < n ; i ++){
if ( blossom [ b a s e [ i ] ] ) {
void markPath ( v i &match , v i &base , v i &blossom , v i base [ i ] = curbase ;
&p , int v , int b , int c h i l d r e n ) { if ( ! used [ i ] ) {
for ( ; b a s e [ v ] != b ; v = p [ match [ v ] ] ) { used [ i ] = true ;
blossom [ b a s e [ v ] ] = blossom [ b a s e [ match [ v ] ] ] = q [ qt++] = i ;
true ; }
p[ v ] = children ; }
c h i l d r e n = match [ v ] ; }
} }
} else if ( p [ t o ] == −1){
p [ to ] = v ;
int f i n d P a t h ( v e c t o r <vi > &graph , v i &match , v i &p , if ( match [ t o ] == −1)
int r o o t ) { return t o ;
int n = graph . s i z e ( ) ; t o = match [ t o ] ;
v i used ( n , 0 ) ; used [ t o ] = true ;
f i l l ( p . b e g i n ( ) , p . end ( ) , −1) ; q [ qt++] = t o ;
v i base (n , 0) ; }
for int
( i = 0 ; i < n ; i ++) }
base [ i ] = i ; }
return − 1;
used [ r o o t ] = 1 ; }
int qh = 0 , qt = 0 ;
int maxMatching ( v e c t o r <vi > &graph ) {
vi q (n , 0) ; int n = graph . s i z e ( ) ;
CAPÍTULO 4. GRAFOS 27

v i match ( n , −1) ; }
vi p(n , 0) ; }
for int
( i = 0 ; i < n ; i ++){ }
if ( match [ i ] == −1){
int v = f i n d P a t h ( graph , match , p , i ) ; int matches = 0 ;
while ( v != −1){ for ( int i = 0 ; i < n ; i ++)
int pv = p [ v ] ; if ( match [ i ] != −1)
int ppv = match [ pv ] ; matches++;
match [ v ] = pv ; return matches ;
match [ pv ] = v ; }
v = ppv ;

4.12 Centroid decomposition


#define MAXN 10000 return u;
v e c t o r <int > t r e e [MAXN] ; }
int subTree [MAXN] , removed [MAXN] , p a r e n t [MAXN] ;
void decompose ( introot , int
p){
int t o t a l V ; totalV = 0;
int d f s 1 ( int u , int p ) { dfs1 ( root , root ) ;
subTree [ u ] = 1 ; int c e n t r o i d = dfs2 ( root , root ) ;
t o t a l V ++; if( p == −1)
for auto
( v : tree [u ]) p = centroid ;
if ( v != p && ! removed [ v ] ) { parent [ centroid ] = p ;
dfs1 (v , u) ; removed [ c e n t r o i d ] = 1 ;
subTree [ u ] += subTree [ v ] ; for auto
( v : tree [ centroid ])
} if ( ! removed [ v ] && v != p )
} decompose ( v , c e n t r o i d ) ;

int d f s 2 ( int u , int p ) { }


for ( auto v : t r e e [ u ] )
if ( v != p && ! removed [ v ] && subTree [ v ] > // Chamar na main
totalV /2) decompose ( 0 , −1) ;
return d f s 2 ( v , u ) ;

4.13 Heavy-Light Decomposition


Divide a árvore em logn cadeias com isso pode responder consultas de máximo/mínimo/soma em um caminho entre dois
vértices em log 2 n se utilizar uma Segment Tree.

head [ c n t ] = u ;
#define MAXN 100100 chainNode [ u ] = c n t ;
#define LOG 20 posArray [ u ] = pos ;
p e s o s [ pos++] = v a l ;
v e c t o r <i i > t r e e [MAXN] ;
int p a r e n t [MAXN] [ LOG] , h e i g h t [MAXN] , subTree [MAXN int i d = −1, s z = −1, edge ;
]; for ( auto v : t r e e [ u ] )
int head [MAXN] , chainNode [MAXN] , posArray [MAXN] ; if ( v . f s t != p && subTree [ v . f s t ] > sz ){
int cnt , pos ; s z = subTree [ v . f s t ] ;
int p e s o s [MAXN] ; id = v . f s t ;
edge = v . snd ;
void d f s ( int u , int p , int h ) { }
parent [ u ] [ 0 ] = p ;
height [ u ] = h ; if ( i d != −1)
subTree [ u ] = 1 ; h l d ( id , u , edge ) ;

for ( int i = 1 ; i < LOG; i ++) for ( auto v : tree [u ])


if ( p a r e n t [ u ] [ i − 1] != −1) if ( v . f s t != p && v . f s t != i d ) {
parent [ u ] [ i ] = parent [ parent [ u ] [ i − 1 ] ] [ i −1]; c n t++;
h l d ( v . f s t , u , v . snd ) ;
for ( auto v : tree [u ]) }
if ( v . f s t != p ) { }
d f s ( v . f s t , u , h+1) ;
subTree [ u ] += subTree [ v . f s t ] ; int getLca ( int u , int v ) {
} if ( h e i g h t [ u ] > h e i g h t [ v ] )
} swap ( u , v ) ;
for ( int i = LOG− 1; i >= 0 ; i −−)
void h l d ( int u , int p , int val ){ if ( p a r e n t [ v ] [ i ] != −1 && h e i g h t [ p a r e n t [ v ] [ i ] ]
if ( head [ c n t ] == −1) >= h e i g h t [ u ] )
CAPÍTULO 4. GRAFOS 28

v = parent [ v ] [ i ] ; }
ans = max( ans , g e t ( posArray [ head [ chainU ] ] ,
if ( v == u ) posArray [ u ] ) ) ;
return u ; u = head [ chainU ] ;
u = parent [ u ] [ 0 ] ;
for ( int i = LOG− 1; i >= 0 ; i −−) }
if ( p a r e n t [ u ] [ i ] !=
parent [ v ] [ i ] ) {
v = parent [ v ] [ i ] ; return ans ;
u = parent [ u ] [ i ] ; }
}
return parent [ u ] [ 0 ] ;
int int int int
// Maior aresta entre o path u−v
} solve ( u, v, lca ){
if ( u == v )
return 0;
return
// get () eh a estrutura de dados que sera
max( s o l v e ( u , l c a ) , s o l v e ( v , l c a ) ) ;
int s o l v e ( int u , int v ) {
utilizada
}
int chainU = chainNode [ u ] , chainV = chainNode [ v
];
int ans = 0 ; sizeof p a r e n t ) ;
// IN MAIN
memset ( parent , − 1,
memset ( head , − 1, sizeof head ) ;
while ( 1 ) { c n t = pos = 0 ;
chainU = chainNode [ u ] ; d f s (0 , 0 , 0) ;
if ( chainU == chainV ) { hld (0 , 0 , 0) ;
if ( u == v )
break ;
// Construir alguma estrutura de consulta em range
no array pesos
ans = max( ans , g e t ( posArray [ v ]+1 , // Ele tem tamanho pos , pode ser Segtree ,
posArray [ u ] ) ) ;
break
SparseTable , BIT , etc .
; // b u i l d ( pos ) ;

4.14 Dijkstra
Complexidade < O((V + E)logE) >.

#define INF 0 x 3 f 3 f 3 f 3 f int d = pq . top ( ) . f i r s t , u = pq . top ( ) . s e c o n d ;


typedef pair< int int
, > ii ; pq . pop ( ) ;
typedef v e c t o r <i i > v i i ;
if ( d > d i s t [ u ] )
v e c t o r <v i i > graph ; continue ;
int V, E ;
for ( int i = 0 ; i < graph [ u ] . s i z e ( ) ; i ++){
void dijkstra ( int s ){ i i v = graph [ u ] [ i ] ;
vector< int > d i s t (V, INF ) ; if ( d i s t [ u ] + v . s e c o n d < d i s t [ v . f i r s t ] ) {
dist [ s ] = 0; d i s t [ v . f i r s t ] = d i s t [ u ] + v . second ;
p r i o r i t y _ q u e u e <i i , v e c t o r <i i >, g r e a t e r <i i > > pq pq . push ( i i ( d i s t [ v . f i r s t ] , v . f i r s t ) ) ;
; }
pq . push ( i i ( 0 , s ) ) ; }
}
while ( ! pq . empty ( ) ) { }

4.15 Ahu - Tree isomorsmo


Verica se duas árvores são iguais, ou seja, possui a mesma conguração dos nós. O(nlogn).

queue< int
> que ;
struct tree { prev . a s s i g n ( n , −1) ;
int n; que . push ( prev [ u ] = u ) ;
int
v e c t o r <v e c t o r < >> a d j ; while ( ! que . empty ( ) ) {
tree ( int n) : n(n) , adj (n) { } u = que . f r o n t ( ) ; que . pop ( ) ;
void add_edge ( int src , int dst ) { for auto( v : adj [ u ] ) {
a d j [ s r c ] . push_back ( d s t ) ; if ( prev [ v ] >= 0 ) continue ;
a d j [ d s t ] . push_back ( s r c ) ; que . push ( v ) ;
} prev [ v ] = u ;
vector< int > centers () { }
int
vector< > prev ; }
int u = 0; }
for int ( k = 0 ; k < 2 ; ++k ) { // vector< int
> path = {u } ;
while
double // median on a path
sweep ( u != prev [ u ] )
CAPÍTULO 4. GRAFOS 29

path . push_back ( u = prev [ u ] ) ; for ( int h = S . l a y e r . s i z e ( ) −1; h >= 0 ; −−h ) {


int m = path . s i z e ( ) ; map<v e c t o r <int >, int > bucket ;
if (m % 2 == 0 ) return
{ path [m/2 − 1] , path [m for ( int u : S . l a y e r [ h ] ) {
/2]}; s o r t ( a l l ( longcodeS [ u ] ) ) ;
else return
{ path [m/ 2 ] } ; bucket [ l o n g c o d e S [ u ] ] = 0 ;
} }
for ( int u : T. l a y e r [ h ] ) {
int
v e c t o r <v e c t o r < >> l a y e r ; s o r t ( a l l ( longcodeT [ u ] ) ) ;
vector< int > prev ; bucket [ longcodeT [ u ] ] = 0 ;
int levelize ( int r ) { // s p l i t }
int i d = 0 ;
vertices into

for ( auto &p : bucket ) p . snd


levels
prev . a s s i g n ( n , − 1) ; prev [ r ] = n ; = i d ++;
l a y e r = {{ r } } ; for ( int u : S . l a y e r [ h ] ) {
while (1) { codeS [ u ] = bucket [ l o n g c o d e S [ u ] ] ;
int
vector< > next ; l o n g c o d e S [ S . prev [ u ] ] . push_back ( codeS [ u ] ) ;
for int ( u : l a y e r . back ( ) ) { }
for int ( v : adj [ u ] ) { for ( int u : T. l a y e r [ h ] ) {
if ( prev [ v ] >= 0 ) continue ; codeT [ u ] = bucket [ longcodeT [ u ] ] ;
prev [ v ] = u ; longcodeT [ T. prev [ u ] ] . push_back ( codeT [ u ] ) ;
next . push_back ( v ) ; }
} }
} return codeS [ s ] == codeT [ t ] ;
if ( next . empty ( ) ) break ; }
l a y e r . push_back ( next ) ;
} bool i s o m o r p h i c ( t r e e S , t r e e T) {
return layer . size () ; auto x = S . c e n t e r s ( ) , y = T. c e n t e r s ( ) ;
} if ( x . s i z e ( ) != y . s i z e ( ) ) return false ;
}; if ( i s o m o r p h i c ( S , x [ 0 ] , T, y [ 0 ] ) ) return true ;
return x . s i z e ( ) > 1 && i s o m o r p h i c ( S , x [ 1 ] , T, y
bool i s o m o r p h i c ( t r e e S , int s , t r e e T, int t ) { [0]) ;
if ( S . n != T. n ) return false ; }
if ( S . l e v e l i z e ( s ) != T . l e v e l i z e ( t ) ) return
false ; // Main
tree a(n) , b(n) ;
v e c t o r <v e c t o r <int >> l o n g c o d e S ( S . n+1) , longcodeT a . add_edge ( x , y ) ;
(T. n+1) ; b . add_edge ( z , w) ;
v e c t o r <int > codeS ( S . n ) , codeT (T. n ) ; isomorphic (a , b) ;
Capítulo 5

Matemática
5.1 Eliminação de Gauss com o XOR
Retorna o valor máximo de xor que é possível se obter fazendo xor entre os elementos da array.
Pode ser necessário o ull ou bitset.

m o d i f i e d . pb ( b u c k e t s [ i ] [ 0 ] ) ;
int len ( l l x){ for ( int j = 1; j < buckets [ i ] . s i z e () ; j
int ans = 0 ; ++){
while (x){ l l temp = b u c k e t s [ i ] [ 0 ] ^ b u c k e t s [ i ] [ j
ans++; ];
x >>= 1 ; b u c k e t s [ l e n ( temp ) ] . pb ( temp ) ;
} }
return ans ; }
} }

l l gaussxor ( l l arr [ ] , int n){ // Ans = maximum xor subset


v e c t o r <l l > b u c k e t s [ 6 5 ] ; l l ans = 0 ;
for int
( i = 0 ; i < n ; i ++) for auto
( m : modified )
b u c k e t s [ l e n ( a r r [ i ] ) ] . pb ( a r r [ i ] ) ; if ( ans < ans^m)
ans ^= m;
v e c t o r <l l > m o d i f i e d ; return ans ;
for ( int i = 6 4 ; i ; i −−){ }
if ( b u c k e t s [ i ] . s i z e ( ) ) {

5.2 Fórmula de Legendre


Dados um inteiro n e um primo p, calcula o expoente da maior potência de p que divide n! em O(logn).

l l legendre ( l l n , l l p){ prod ∗= p ;


l l ans = 0 ; }
l l prod = p ; return ans ;
while
( prod <= n ) { }
ans += n/ prod ;

5.3 Número de fatores primos de N!


Dado um N encontra quantos fatores o N! possui

// Sieve of Eratosthenes to mark all prime number for ( int i =2; i ∗ i<=n ; i ++)
{
void int bool if ( prime [ i ] )
// in array prime as 1
sieve ( n, prime [ ] )
{ {
for ( int j=i ∗ i ; j<=n ; j += i )
for ( int
// Initialize all n u m be r s as prime
i =1; i<=n ; i ++) prime [ j ] = 0 ;
prime [ i ] = 1 ; }
}
// Mark composites }
prime [ 1 ] = 0 ;

30
CAPÍTULO 5. MATEMÁTICA 31

l l ans = 1 ;
int int int
// Returns the highest exponent of p in n!
expFactor ( n, p)
{
int x = p ; bool
// Find all primes upto n
prime [ n + 1 ] ;
int exponent = 0; s i e v e ( n , prime ) ;
while ( ( n/x ) > 0)
{
for ( int
// Multiply exponent ( of primes ) added with 1
exponent += n/x ; p=1; p<=n ; p++)
x ∗= p ; {
}
return
// if p is a prime then p is also a
exponent ;
if
// prime factor of n!
} ( prime [ p]==1)
ans ∗= ( expFactor ( n , p ) + 1 ) ;
}
int
// Returns the no of factors in n!
l l countFactors ( n)
{ return ans ;
// ans stores the no of factors in n! }

5.4 Trailing zeros in factorial


int findTrailingZeros ( int n){ for ( int i =5; n/ i >=1; i ∗= 5 )
count += n/ i ;
int
// Initialize result
count = 0 ;
return count ;
// Keep dividing n by powers of 5 and update }
count

5.5 Número de divisores de N!


Dado um N encontra quantos divisores o N! possui

// Function to find all result of factorial number


// allPrimes [ ] stores all prime nu m b er s less u l l f a c t o r i a l D i v i s o r s ( u l l n)
// than or equal to n. {
v e c t o r <u l l > a l l P r i m e s ; s i e v e ( n ) ; // c r e a t e s i e v e

void int
// Fills above vector allPrimes [ ] for a given n // Initialize result
sieve ( n) ull result = 1;
{
// Create a boolean array " prime [ 0 . . n ] " and // find exponents of all primes which divides n

for ( int
// initialize all entries it as true . A value // and less than n
// in prime [ i ] will finally be false if i is i =0; i < a l l P r i m e s . s i z e ( ) ; i ++)
{
bool> true ) ;
// not a prime , else true .
vector< prime ( n+1, // Current divisor
u l l p = allPrimes [ i ] ;

for ( int
// Loop to update prime [ ]
p=2; p ∗ p<=n ; p++) // Find the highest power ( stored in exp ) '
{ // of allPrimes [ i ] that divides n using
// If prime [ p ] is not changed , then it // Legendre ' s formula .
u l l exp = 0 ;
if true ) while
// is a prime
( prime [ p ] == ( p <= n )
{ {
exp = exp + ( n/p ) ;
for ( int
// Update all multiples of p
i=p ∗ 2 ; i<=n ; i += p ) p = p∗ a l l P r i m e s [ i ] ;
prime [ i ] = ; false }
}
} // Multiply exponents of all primes less
// than n
r e s u l t = r e s u l t ∗ ( exp +1) ;
for ( int p=2;
// Store primes in the vector allPrimes
p<=n ; p++) }
if ( prime [ p ] )
a l l P r i m e s . push_back ( p ) ;
return
// return total divisors
} result ;
}
CAPÍTULO 5. MATEMÁTICA 32

5.6 Grundy Number


Faz o xor de todos os números grundy de todas as pilhas, se for diferente de 0 ganha o jogo.

if ( x p e r d e j o g o )
l l mex ( unordered_set<l l > s t ) { return 0 ;
l l ans = 0 ;
while ( s t . count ( ans ) ) ans++; unordered_set<l l > s t ;
return ans ; for int
( i = 0 ; i < l ; i ++)
} s t . i n s e r t ( grundy ( novoX ) ) ;
return
// Transicoes
mex ( s t ) ;
l l grundy ( int x){ }

5.7 Baby-Step Giant-Step para Logaritmo Discreto


Resolve a equação ax = b(modm) em O(sqrt(m)logm). Retorna -1 se não há solução.

template typename
< T> }
T baby (T a , T b , T m) { for (T i =0, c u r=b ; i<=n ; ++i ) {
a %= m; b %= m; if ( v a l s . count ( c u r ) ) {
T n = (T) s q r t (m + . 0 ) + 1 ; T ans = v a l s [ c u r ] ∗ n − i ;
T an = 1 ; if ( ans < m)
for (T i =0; i <n ; ++i ) return ans ;
an = ( an ∗ a ) % m; }
map<T, T> v a l s ; c u r = ( c u r ∗ a ) % m;
for (T i =1, c u r=an ; i<=n ; ++i ) { }
if
( ! v a l s . count ( c u r ) ) return − 1;
v a l s [ cur ] = i ; }
c u r = ( c u r ∗ an ) % m;

5.8 Baby-Step Giant-Step FAST


Resolve a equação ax = b(modm) em O(sqrt(m)logm). Retorna -1 se não há solução.

class Hash ll x, y, z;
{ Triple ( const
ll a, const ll b, const l l c) : x(
static const int HASHMOD = 7 6 7 9 9 7 7 ; a) , y(b) , z ( c ) { }
int top , myhash [HASHMOD + 1 0 0 ] , v a l u e [HASHMOD + };
1 0 0 ] , s t a c k [ 1 << 1 6 ] ;
int l o c a t e ( const int x ) const T r i p l e ExtendedGCD ( const ll a, const
l l b)
{ {
int h = x % HASHMOD; if ( b == 0 ) return Triple (1 , 0 , a) ;
while ( myhash [ h ] != −1 && myhash [ h ] != x ) ++ const T r i p l e l a s t = ExtendedGCD ( b , a%b ) ;
h; return Triple ( last . y , last . x − a / b ∗ last . y ,
return h ; last . z) ;
} }
public :
Hash ( ) : top ( 0 ) { memset ( myhash , 0xFF , sizeof ( l l BabyStep ( l l A, l l B, l l C)
myhash ) ) ; } {
void i n s e r t ( const int x , const int v ) const int sqrtn = static_cast int
< >( s t d : : c e i l (
{ s t d : : s q r t (C) ) ) ;
const int h = l o c a t e ( x ) ; l l base = 1 ;
if ( myhash [ h ] == −1) myhash . c l e a r ( ) ;
myhash [ h ] = x , v a l u e [ h ] = v , s t a c k [++top ] = for int
( i = 0 ; i < s q r t n ; ++i )
h; {
} myhash . i n s e r t ( base , i ) ;
int const int x ) const
get ( b a s e = b a s e ∗A % C;
{ }
const int h = l o c a t e ( x ) ; l l i = 0 , j = − 1, D = 1 ;
return myhash [ h ] == x ? v a l u e [ h ] : −1; for ( ; i < s q r t n ; ++i )
} {
void c l e a r ( ) { while ( top ) myhash [ s t a c k [ top − −]] T r i p l e r e s = ExtendedGCD (D, C) ;
= − 1; } const int c = C / res . z ;
} myhash ; res . x = ( res . x ∗ B / res . z % c + c) % c ;
j = myhash . g e t ( r e s . x ) ;
struct Triple if ( j != −1) return
i ∗ sqrtn + j ;
{ D = D ∗ base % C;
CAPÍTULO 5. MATEMÁTICA 33

} }
return − 1;

5.9 Números de Catalan


Computa os números de Catalan de 0 até n em (nlogn).
Olhar mais exemplos no CP3 pg. 206
• Cat(n) = número de árvores binárias completas de n+1 folhas ou 2*n + 1 elementos
• Cat(n) = número de combinações válidas para n pares de parêntesis.
• Cat(n) = número de formas que o parentesiação de n+1 elementos pode ser feito.
• Cat(n) = número de triangulações de um polígono convexo de n+2 lados.
• Cat(n) = número de caminhos monotônicos discretos para ir de (0,0) a (n,n).

g = gcd ( 2 ∗ ( 2 ∗ i − 1) , i +1) ;
l l c a t [MAXN] ; c a t [ i ] = ( ( 2 ∗ ( 2 ∗ i − 1) ) /g ) ∗ ( c a t [ i − 1 ] / ( ( i +1)/g )
void catalan ( intn){ );
cat [ 0 ] = cat [ 1 ] = 1; }
ll g; }
for int( i = 2 ; i<=n ; i ++){

5.10 Fórmulas úteis


Olhar mais fórmulas no CP3 pg. 345
• Soma dos n primeiros bonacci: f (n + 2) − 1.
• Soma dos n primeiros bonacci ao quadrado: f (n) ∗ f (n + 1).
• Soma dos quadrados de todos números de 1 até n: n ∗ (n + 1) ∗ (2n + 1)/6.
• Fórmula de Cayley: existem nn−2 árvores geradoras em um grafo completo de n vértices.
• Desarranjo: o número der(n) de permutações de n elementos em que nenhum dos elementos ca na posição original
é dado por: der(n) = (n − 1)(der(n − 1) + der(n − 2)), onde der(0) = 1 e der(1) = 0.
• Teorema de Erdos P Gallai: é condição
Pk suciente para que
Pk uma array represente os graus dos vértices de um nó:
d1 ≥ d2 ≥ ... ≥ dn , i=1 di = 2k , i=1 di ≤ k(k − 1) + i=k+1 min(di , k).
n

• Fórmula de Euler para grafos planares: V − E + F = 2, onde F é o número de faces.


• Círculo de Moser: o número de peças em que um círculo pode ser divido por cordas ligadas a n pontos tais que não
se tem 3 cordas internamente concorrentes é dada por: g(n) = C4n + C2n + 1.
• Teorema de Pick: se I é o número de pontos inteiros dentro de um polígono, A a área do polígono e b o número de
pontos inteiros na borda, então A = i + b/2 − 1 .
• O número de árvores geradores em um grafo bipartido completo é mn−1 × nm−1 .
• Teorema de Kirchho: o número de árvores geradoras em um grafo é igual ao cofator da sua matriz laplaciana L.
L = D − A, em que D é uma matriz diagonal em que aii = di e A é a matriz de adjacência.
• Teorema de Konig: a cobertura mínima de vértices em um grafo bipartido (o número mínimo de vértices a serem
removidos para se remover todas as arestas) é igual ao pareamento máximo do grafo.
• Teorema de Zeckendorf: qualquer inteiro positivo pode ser representado pela soma de números de Fibonacci que
não inclua dois números consecutivos. Para achar essa soma, usar o algoritmo guloso, sempre procurando o maior
número de bonacci menor que o número.
• Teorema de Dilworth: em um DAG que representa um conjunto parcialmente ordenado, uma cadeia é um subcon-
junto de vértices tais que todos os pares dentro dele são comparáveis; uma anti-cadeia é um subconjunto tal que
todos os pares de vértices dele são não comparáveis. O teorema arma que a partição mínima em cadeias é igual ao
comprimenton da maior anti-cadeia. Para computar, criar um grafo bipartido: para cada vértice x, duplicar para
ux e vx . Uma aresta x → y é escrita como ux → vy . O tamanho da partição mínima, também chamada de largura
do conjunto, é N − o emparelhamento máximo.
• Teorema de Mirsky: semelhante ao teorema de Dilworth, o tamanho da partição mínima em anti-cadeias é igual ao
comprimento da maior cadeia.
CAPÍTULO 5. MATEMÁTICA 34

5.11 Fast Fourier Transform - FFT


if ( i < j ) swap ( a [ i ] , a [ j ] ) ;
struct b a s e { }
double x , y ;
b a s e ( ) : x ( 0 ) , y ( 0 ) {} for ( int l e n =2; l e n<=n ; l e n <<=1) {
b a s e ( double a , double b=0) : x ( a ) , y ( b ) {} double ang = 2 ∗M_PI/ l e n ∗ ( i n v e r t ? −1 : 1 ) ;
b a s e operator /=( double k ) { x/=k ; y/=k ; return b a s e wlen ( c o s ( ang ) , s i n ( ang ) ) ;
( ∗ this ) ; } for ( int i =0; i <n ; i+=l e n ) {
b a s e operator ∗ ( b a s e a ) const { return b a s e ( x ∗ a . b a s e w( 1 ) ;
x − y∗a . y , x∗a . y + y∗a . x ) ; } for ( int j =0; j <l e n / 2 ; ++j ) {
b a s e operator ∗ =( b a s e a ) { b a s e u = a [ i+j ] , v = a [ i+j+l e n / 2 ] ∗ w
double tx = x ∗ a . x − y ∗ a . y ; ;
double ty = x ∗ a . y + y ∗ a . x ; a [ i+j ] = u + v ;
x = tx ; y = ty ; a [ i+j+l e n / 2 ] = u − v ;
return ( ∗ this ) ; w ∗= wlen ;
} }
b a s e operator +( b a s e a ) const { return b a s e ( x+a . }
x , y+a . y ) ; } }
b a s e operator −( b a s e a ) const { return b a s e ( x−a . if ( i n v e r t )
x , y−a . y ) ; } for ( int i =0; i <n ; ++i )
double r e a l ( ) { return x ; } a [ i ] /= n ;
double imag ( ) { return y ; } }
};
void c o n v o l u t i o n ( v e c t o r <base> a , v e c t o r <base> b ,
typedef complex< double> base ; v e c t o r <base> & r e s ) {
int n = 1 ;
// Se tiver com

while ( n < max( a . s i z e ( ) , b . s i z e ( ) ) ) n <<= 1 ;


tempo bom

void f f t ( v e c t o r <base> & a , bool i n v e r t ) { n <<= 1 ;


int n = ( int ) a . s i z e ( ) ; a . r e s i z e (n) , b . r e s i z e (n) ;
for ( int i =1, j =0; i <n ; ++i ) { f f t (a , false ) ; f f t (b , false );
int b i t = n >> 1 ; res . r e s i z e (n) ;
for ( ; j>=b i t ; b i t >>=1) for int
( i =0; i <n ; ++i ) r e s [ i ] = a [ i ] ∗ b [ i ] ;
j −= b i t ; f f t ( res , true );
j += b i t ; }

5.12 Convolução Circular


template <typename T>
void c i r c u l a r c o n v o l u t i o n ( v e c t o r <T> a , v e c t o r <T> b , v e c t o r <T> & r e s ) {
int n = a . s i z e ( ) ;
b . i n s e r t ( b . end ( ) , b . b e g i n ( ) , b . end ( ) ) ;
convolution (a , b , res ) ;
r e s = v e c t o r <T>( r e s . b e g i n ( )+n , r e s . b e g i n ( ) +(2 ∗ n ) ) ;
}
Capítulo 6

Processamento de Strings
6.1 Aho-Corasick
Após inserir todas as strings, chamar a função aho();

int u = q . f r o n t ( ) ; q . pop ( ) ;
#define MAXN 100100 for ( int i = 0 ; i < ALPHA; i ++){
#define ALPHA 15 if ( t r i e [ u ] [ i ] ) {
int v = f a i l u r e [ u ] ;
int t r i e [MAXN] [ ALPHA ] ; while ( v && ! t r i e [ v ] [ i ] )
int term [MAXN] ; v = failure [v ];
int f a i l u r e [MAXN] ; v = trie [v ][ i ];
int c n t ; failure [ trie [u ][ i ]] = v;
void i n s e r t ( s t r i n g s ) { term [ t r i e [ u ] [ i ] ] |= term [ v ] ;
int node = 0 ; q . push ( t r i e [ u ] [ i ] ) ;
for ( auto c : s ) { }
if ( ! t r i e [ node ] [ c− ' a ' ] ) }
t r i e [ node ] [ c− ' a ' ] = c n t++; }
node = t r i e [ node ] [ c− ' a ' ] ; }
}
term [ node ] = 1 ; int next ( int node , int c ) {
} while ( node && ! t r i e [ node ] [ c ] )
node = f a i l u r e [ node ] ;
void aho ( ) { return t r i e [ node ] [ c ] ;
queue< int> q; }

for ( int i = 0 ; i < ALPHA; i ++){ void init () {


if ( t r i e [ 0 ] [ i ] ) { memset ( t r i e , 0 , sizeof t r i e ) ;
failure [ trie [ 0 ] [ i ] ] = 0; memset ( term , 0 , sizeof term ) ;
q . push ( t r i e [ 0 ] [ i ] ) ; sizeof f a i l u r e ) ;
memset ( f a i l u r e , 0 ,
} memset ( v i s , 0 , sizeof v i s ) ;
} cnt = 1 ;
}
while ( ! q . empty ( ) ) {

6.2 Rabin-Karp
String matching O(|S| + |T |).

s t r i n g s , t ; // i n p u t u l l h_s = 0 ;
const int p = 31; for ( int i = 0 ; i < s . s i z e ( ) ; i ++)
v e c t o r <u l l > p_pow(max( s . s i z e ( ) , t . s i z e ( ) ) ) ; h_s += ( s [ i ] − ' a ' +1) ∗ p_pow [ i ] ;
p_pow [ 0 ] = 1 ;
for int
( i = 1 ; i < p_pow . s i z e ( ) ; i ++) for ( int i = 0 ; i + s . s i z e ( ) −1 < t . s i z e ( ) ; i ++){
p_pow [ i ] = p_pow [ i − 1] ∗ p ; u l l cur_h = h [ i+s . s i z e ( ) − 1];
if ( i )
v e c t o r <u l l > h ( t . s i z e ( ) ) ; cur_h −= h [ i − 1 ] ;
for ( int i = 0 ; i < t . s i z e ( ) ; i ++){ if ( cur_h == h_s ∗ p_pow [ i ] )
h [ i ] = ( t [ i ] − ' a ' +1) ∗ p_pow [ i ] ; c o u t << i << " " ;
if ( i ) }
h [ i ] += h [ i − 1 ] ;

35
CAPÍTULO 6. PROCESSAMENTO DE STRINGS 36

6.3 Repetend: menor período de uma string


Menor período de uma string em O(n).

while ( j >=0 && s [ j ] != s [ i − 1])


#define MAXN 100010 j = nxt [ j ] ;
nxt [ i ] = j +1;
int r e p e t e n d ( s t r i n g s ) { }
int n = s . s i z e ( ) ; int a = n−nxt [ n ] ;
int nxt [ n + 1 ] ; if ( n%a==0)
nxt [ 0 ] = − 1; return a ;
for ( int i = 1 ; i <= n ; i ++){ return n ;
int j = nxt [ i − 1 ] ; }

6.4 Sux Array


#define MAXN 100100 memset (RA, 0 , sizeof
RA) ;
int s u f f i x [MAXN] ; for int
( i = 0 ; i < n ; i ++){
int RA[MAXN] , aux [MAXN] , l c p [MAXN] , i n v S u f f i x [MAXN suffix [ i ] = i ;
] , c [MAXN] ; RA[ i ] = p [ i ] ;
// Lembrar de colocar o ultimo caractere alguem }

for ( int
menor que o alfabeto
// A . . Z pode usar $ k = 1 ; k < n ; k <<= 1 ) {
// a.. z pode usar { c o u n t i n g S o r t ( k ) ; // Ordena p o r second
string p; c o u n t i n g S o r t ( 0 ) ; // Ordena p o r first

aux [ s u f f i x [ 0 ] ] = 0 ;
bool cmpSlow ( int a , int b ) { int
// O( n^2 logn )
newRa = 0 ;
return p . s u b s t r ( a ) < p . s u b s t r ( b ) ; for int
( i = 1 ; i < n ; i ++){
} if (RA[ s u f f i x [ i ] ] == RA[ s u f f i x [ i − 1 ] ] &&
RA[ s u f f i x [ i ]+k ] == RA[ s u f f i x [ i −1]+
void saSlow ( ) { k])
for ( int i = 0 ; i < p . s i z e ( ) ; i ++) aux [ s u f f i x [ i ] ] = newRa ;
suffix [ i ] = i ; else
s o r t ( s u f f i x , s u f f i x+p . s i z e ( ) , cmpSlow ) ; aux [ s u f f i x [ i ] ] = ++newRa ;
} }
for ( int i = 0 ; i < n ; i ++)
void l c p S l o w ( ) { RA[ i ] = aux [ i ] ;
l c p [ p . s i z e ( ) − 1] = 0 ; if (RA[ s u f f i x [ n − 1 ] ] == n −1)
for ( int i = 0 ; i < p . s i z e ( ) −1; i ++){ break ;
int l = 0 ; }
while ( p [ s u f f i x [ i ]+ l ] == p [ s u f f i x [ i +1]+ l ] ) l }
++;
lcp [ i ] = l ; void l c p F a s t ( ) {
} l c p [ n − 1] = 0 ;
} for ( int i = 0 ; i < n ; i ++)
invSuffix [ suffix [ i ] ] = i ;

int k = 0 ;
// O( n l o g ^2(n ) ) − Se usar o sort ()

int n ; for ( int i = 0 ; i < n ; i ++){


// O( n logn ) − Se usar countingSort

void c o u n t i n g S o r t ( int k ) { if ( i n v S u f f i x [ i ] == n −1){


memset ( c , 0 , sizeof c ) ; k = 0;
int maxi = max ( 3 0 0 , n ) ; continue ;
for ( int i = 0 ; i < n ; i ++) }
c [RA[ i+k ] ] + + ; int j = s u f f i x [ i n v S u f f i x [ i ] + 1 ] ;
int sum = 0 ; while ( i+k<n && j+k<n && p [ i+k]==p [ j+k ] ) k++;
for ( int i = 0 ; i < maxi ; i ++){ lcp [ invSuffix [ i ] ] = k ;
int aux = c [ i ] ; if ( k )
c [ i ] = sum ; k −−;
sum += aux ; }
} }
for ( int i = 0 ; i < n ; i ++)
aux [ c [RA[ s u f f i x [ i ]+k ] ] + + ] = suffix [ i ];
for ( int i = 0 ; i < n ; i ++) int s z [MAXN] ;
// Para LCS de muitas strings

s u f f i x [ i ] = aux [ i ] ; int owner [MAXN] , s e p a r a t o r s [MAXN] ;


} int words ;
void saFast () { void buildOwner ( ) {
n = p . size () ; memset ( owner , 0 , sizeof owner ) ;
CAPÍTULO 6. PROCESSAMENTO DE STRINGS 37

for ( int i = 0 ; i < n ; i ++){ if ( s u f f i x [ i ] < s z [ j ] ) {


if ( s e p a r a t o r s [ s u f f i x [ i ] ] ) { owner [ i ] = j ;
owner [ i ] = − 1; break ;
continue ; }
} }
for ( int j = 0 ; j < words ; j ++) }

6.5 Z Function
Criação do array Z em O(n).

vector< int
> z_function ( s t r i n g s ) { ++z [ i ] ;
intn = ( int ) s . length () ; if (i + z[ i ] − 1 > r)
vector< int > z (n) ; l = i , r = i + z [ i ] − 1;
for int
( i = 1 , l = 0 , r = 0 ; i < n ; ++i ) { }
if( i <= r ) return z;
z [ i ] = min ( r − i + 1 , z [ i − l ] ) ; }
while ( i + z [ i ] < n && s [ z [ i ] ] == s [ i + z [ i
]])

6.6 KMP
Matching O(n).

#define SZ 1000 int kmpSearch ( ) {


int T[ s z ] , P [ s z ] , b [ s z ] ; int i = 0 , j = 0 , ans = 0 ;
int n , m; while ( i < n ) {
// T = T e x t , P = Patern

while ( j >= 0 && T [ i ] !=


// n = |T| , m = |P|
P[ j ] )
void kmpPre ( ) { j = b[ j ];
int i = 0 , j = −1; i ++, j ++;
b [ 0 ] = − 1; if ( j == m) {
while ( i < m) { ans++;
while ( j >= 0 && P [ i ] != P [ j ] ) // Encontrado no indice i − j
j = b[ j ]; j = b[ j ];
i ++, j ++; }
b[ i ] = j ; }
} return ans ;
} }
Capítulo 7

Geometria Computacional
7.1 Template - Júnior
#define p i a c o s ( − 1.0) a = t .y − s .y;
#define e p s 1 e −6 b = s .x − t .x;
c = −a ∗ s . x − b ∗ s . y ;
struct Point { }
double x , y ; bool p a r a l l e l ( Line o t h e r ) { return fabs (a ∗
Point ( ) { } ; other . b − b ∗ other . a ) < eps ; }
Point ( double _x , double _y) { Point i n t e r s e c t ( Line o t h e r ) {
x = _x ; if this
( return
−>p a r a l l e l ( o t h e r ) ) Point (−
y = _y ; HUGE_VAL, −HUGE_VAL) ;
} else {
void r e a d ( ) { s c a n f ( "%l f %l f " , &x , &y ) ; } double determinant = this −>b ∗ o t h e r . a
double d i s t a n c e ( Point o t h e r ) { return hypot ( this −>a ∗ o t h e r . b ;
double this this

x − other . x , y − other . y) ; } x = ( −>c ∗ o t h e r . b − −>
Point operator + ( Point o t h e r ) { return b ∗ other . c ) / determinant ;
Point ( x + o t h e r . x , y + o t h e r . y ) ; } double this
y = ( −>a ∗ o t h e r . c − this −>
Point operator − ( Point o t h e r ) { return c ∗ other . a ) / determinant ;
Point ( x − o t h e r . x , y − o t h e r . y ) ; } return Point ( x , y ) ;
Point operator ∗ ( double t ) { return Point ( x }
∗ t , y ∗ t); } }
Point operator / ( double t ) { return Point ( x Line p e r p e n d i c u l a r ( Point p o i n t ) {
/ t , y / t); } return Line (−b , a , b ∗ p o i n t . x − a ∗
double operator ∗ ( Point q ) { return x ∗ q . x point . y) ;
+ y ∗ q . y;} }
double
// a ∗ b = | a | | b | c o s ( ang ) //
Positivo se o vetor B esta do mesmo lado d i s t a n c e ( Point r ) {
Point p , q ;
double operator % return if
do vetor perpendicular a A
( Point q ) { x ∗ q.y ( fabs (b) < eps ) {
− y ∗ q . x;} // a%b = | a | | b | s i n ( ang ) // p = Point (− c / a , 0 ) ;
q = Point (( − c − b ) / a , 1 ) ;
double return
Angle of vectors
polar () { ( ( y > − e p s ) ? atan2 ( }
y , x ) : 2 ∗ p i + atan2 ( y , x ) ) ; } else {
Point r o t a t e ( double return
t) { Point ( x ∗ p = Point ( 0 , −c / b ) ;
cos ( t ) − y ∗ sin ( t ) , x ∗ sin ( t ) + y ∗ q = Point ( 1 , (− c − a ) / b ) ;
cos ( t ) ) ; } }
double
Point r o t a t e A r o u n d P o i n t ( t , Point p ) { Point A = r − q , B = r − p , C = q − p ;
return this ( − p) . rotate ( t ) + p ; double a = A ∗ A, b = B ∗ B, c = C ∗ C;
} return f a b s (A % B) / s q r t ( c ) ;
bool operator < ( Point o t h e r ) const { }
if ( o t h e r . x != x ) return x < other . x ; };
else return y < other . y ;
} class G e o m e t r i c U t i l s {
}; public :
GeometricUtils () {};
struct Line { static double c r o s s ( Point a , Point b , Point
double a , b , c ; c) {
Line ( ) { } ; double dx1 = ( a . x−b . x ) , dy1 = ( a . y−b . y ) ;
Line ( double _a , double _b, double _c) { double dx2 = ( c . x−b . x ) , dy2 = ( c . y−b . y ) ;
a = _a ; return ( dx1 ∗ dy2 − dx2 ∗ dy1 ) ;
b = _b ; }
c = _c ; static bool above ( Point a , Point b , Point c )
} {
Line ( Point s , Point t ) { return c r o s s ( a , b , c ) < 0 ;

38
CAPÍTULO 7. GEOMETRIA COMPUTACIONAL 39

} else {
static bool under ( Point a , Point b , Point c ) double a1 = 2 . ∗ a c o s ( ( d ∗ d + r ∗ r − c
{ . r ∗ c . r ) / (2. ∗ d ∗ r ) ) ;
return c r o s s ( a , b , c ) > 0 ; double a2 = 2 . ∗ a c o s ( ( d ∗ d + c . r ∗ c . r
} − r ∗ r ) / (2. ∗ d ∗ c . r ) ) ;
static bool sameLine ( Point a , Point b , Point double num1 = ( l d ) a1 / 2 . ∗ r ∗ r − r
c) { ∗ r ∗ s i n ( a1 ) ∗ 0 . 5 ;
return c r o s s ( a , b , c ) < e p s ; double num2 = ( l d ) a2 / 2 . ∗ c . r ∗ c . r
} − c . r ∗ c . r ∗ s i n ( a2 ) ∗ 0 . 5 ;
static double s e g D i s t a n c e ( Point p , Point q , return num1 + num2 ;
Point r ) { }
Point A = r − q , B = r − p , C = q − p ; }
double a = A ∗ A, b = B ∗ B, c = C ∗ C; };
if (cmp( b , a + c ) >= 0 ) return
sqrt (a) ;
else if (cmp( a , b + c ) >= 0 ) return
sqrt ( Point g e t C i r c u n c e n t e r ( Point a , Point b , Point c
b) ; ) {
else return f a b s (A % B) / s q r t ( c ) ; Line l 1 = Line ( a , b ) ;
} double xab = ( a . x + b . x ) ∗ 0 . 5 , yab = ( a . y +
}; b. y) ∗ 0.5;
Line l 2 = Line ( b , c ) ;
struct C i r c l e { double xbc = ( b . x + c . x ) ∗ 0 . 5 , ybc = ( b . y +
double x , y , r ; c . y) ∗ 0.5;
Circle () {}; l 1 = l 1 . p e r p e n d i c u l a r ( Point ( xab , yab ) ) ;
C i r c l e ( double _x , double _y , double _r ) { l 2 = l 2 . p e r p e n d i c u l a r ( Point ( xbc , ybc ) ) ;
x = _x ; return l1 . intersect ( l2 ) ;
y = _y ; }
r = _r ;
} v e c t o r < Point > ConvexHull ( v e c t o r < Point > &
C i r c l e ( Point a , Point b , Point c ) { polygon ) {
Line ab = Line ( a , b ) ; s o r t ( polygon . b e g i n ( ) , polygon . end ( ) ) ;
Line bc = Line ( b , c ) ; v e c t o r < Point > down , up ;
double xAB = ( a . x + b . x ) ∗ 0 . 5 ; up . pb ( polygon [ 0 ] ) ;
double yAB = ( a . y + b . y ) ∗ 0 . 5 ; up . pb ( polygon [ 1 ] ) ;
double xBC = ( b . x + c . x ) ∗ 0 . 5 ; down . pb ( polygon [ 0 ] ) ;
double yBC = ( b . y + c . y ) ∗ 0 . 5 ; down . pb ( polygon [ 1 ] ) ;
ab = ab . p e r p e n d i c u l a r ( Point (xAB, yAB) ) ; for int( i = 2 ; i < polygon . s i z e ( ) ; ++i ) {
bc = bc . p e r p e n d i c u l a r ( Point (xBC, yBC) ) ; while ( up . s i z e ( ) >= 2 && G e o m e t r i c U t i l s .
if ( ab . p a r a l l e l ( bc ) ) { above ( up [ up . s i z e ( ) − 2 ] , up [ up . s i z e ( )
x = − 1; − 1 ] , polygon [ i ] ) ) up . pop_back ( ) ;
y = − 1; while ( down . s i z e ( ) >= 2 && G e o m e t r i c U t i l s .
r = − 1; under ( down [ down . s i z e ( ) − 2 ] , down [
} down . s i z e ( ) − 1 ] , polygon [ i ] ) ) down .
Point c e n t e r = ab . i n t e r s e c t ( bc ) ; pop_back ( ) ;
x = center . x ; up . pb ( polygon [ i ] ) ;
y = center . y ; down . pb ( polygon [ i ] ) ;
r = center . distance (a) ; }
} v e c t o r < Point > s o l = up ;
double getIntersectionArea ( Circle c ) { for int( i = down . s i z e ( ) − 2 ; i > 0 ; −− i ) s o l
double d = hypot ( x − c . x , y − c . y ) ; . pb ( down [ i ] ) ;
if ( d >= r + c . r ) return 0.0; return sol ;
else if ( c . r >= d + r ) return pi ∗ r ∗ r ; }
else if ( r >= d + c . r ) return pi ∗ c . r ∗
c.r;

7.2 Menor círculo


Menor círculo que engloba todos os pontos. O(n).

struct p o i n t { double norm ( ) {


double x , y ; return x ∗ x + y ∗ y ;
p o i n t ( ) {} }
p o i n t ( double
_x , double _y) { double c r o s s ( p o i n t p ) {
x = _x , y = _y ; return x ∗ p . y − y ∗ p . x ;
} }
point subtract ( point p) { };
return p o i n t ( x−p . x , y−p . y ) ; struct c i r c l e {
} double x , y , r ;
void r e a d ( ) { s c a n f ( "%l f %l f " , &x , &y ) ; } c i r c l e ( ) {}
double distance ( point p){ c i r c l e ( double _x , double
_y , double _r ) {
return hypot ( x−p . x , y−p . y ) ; x = _x , y = _y , r = _r ;
} }
CAPÍTULO 7. GEOMETRIA COMPUTACIONAL 40

c i r c l e ( point a , double b){ pq . c r o s s ( p o i n t ( l e f t −>x , l e f t −>y ) .


x = a.x, y = a.y; subtract (p) ) ) )
r = b; left = c;
} else if ( c r o s s < 0 && ( r i g h t == NULL | | pq .
bool contains ( point p){ c r o s s ( p o i n t ( c−>x , c−>y ) . s u b t r a c t ( p ) ) <
return p o i n t ( x , y ) . d i s t a n c e ( p ) <= r + e p s ; pq . c r o s s ( p o i n t ( r i g h t −>x , r i g h t −>y ) .
} subtract (p) ) ) )
bool c o n t a i n s ( v e c t o r <p o i n t > ps ) { right = c ;
for auto ( p : ps ) }
if ( ! contains (p) ) return r i g h t == NULL | | l e f t != NULL && l e f t −>r
return 0; <= r i g h t −>r ? ∗ l e f t : ∗ r i g h t ;
return 1; }
}
}; c i r c l e makeCircleOnePoint ( v e c t o r <p o i n t > p o i n t s ,
point p){
c i r c l e ∗ makeCircumcircle ( point a , point b , point c c i r c l e c = c i r c l e (p , 0) ;
){ for int( i = 0 ; i < p o i n t s . s i z e ( ) ; i ++){
double d = (a . x ∗ (b . y − c . y) + b . x ∗ ( c . y − a . point q = points [ i ] ;
y) + c . x ∗ (a . y − b . y) ) ∗ 2; if ( ! c . contains (q) ){
if ( d == 0 ) if ( c . r == 0 )
return NULL; c = makeDiameter ( p , q ) ;
double x = ( a . norm ( ) ∗ ( b . y − c . y ) + b . norm ( ) ∗ else {
( c . y − a . y ) + c . norm ( ) ∗ ( a . y − b . y ) ) / d ; v e c t o r <p o i n t > aux(& p o i n t s [ 0 ] , &p o i n t s [
double y = ( a . norm ( ) ∗ ( c . x − b . x ) + b . norm ( ) ∗ i + 1]) ;
( a . x − c . x ) + c . norm ( ) ∗ ( b . x − a . x ) ) / d ; c = makeCircleTwoPoints ( aux , p , q ) ;
point p = point (x , y) ; }
return new c i r c l e (p , p . distance (a) ) ; }
} }
return c;
c i r c l e makeDiameter ( p o i n t a , p o i n t b ) { }
return c i r c l e ( point (( a . x + b . x)/ 2 , (a . y + b . y)
/ 2) , a . d i s t a n c e (b) / 2) ; c i r c l e m a k e C i r c l e ( v e c t o r <p o i n t > p o i n t s ) {
} v e c t o r <p o i n t > s h u f f l e d = p o i n t s ;
random_shuffle ( s h u f f l e d . b e g i n ( ) , s h u f f l e d . end ( )
c i r c l e makeCircleTwoPoints ( v e c t o r <p o i n t > p o i n t s , );
point p , point q){
c i r c l e temp = makeDiameter ( p , q ) ; circle c;
if ( temp . c o n t a i n s ( p o i n t s ) ) bool f i r s t = true ;
return temp ; for ( int i = 0 ; i < s h u f f l e d . s i z e ( ) ; i ++){
point p = sh u f f l e d [ i ] ;
c i r c l e ∗ l e f t = NULL; if ( f i r s t | | ! c . c o n t a i n s ( p ) ) {
c i r c l e ∗ r i g h t = NULL; v e c t o r <p o i n t > aux(& s h u f f l e d [ 0 ] , &s h u f f l e d
[ i + 1]) ;
for ( p o i n t r : p o i n t s ) { c = makeCircleOnePoint ( aux , p ) ;
p o i n t pq = q . s u b t r a c t ( p ) ; first = false ;
double c r o s s = pq . c r o s s ( r . s u b t r a c t ( p ) ) ; }
c i r c l e ∗c = makeCircumcircle (p , q , r ) ; }
if ( c == NULL) return c;
continue ; }
else if ( c r o s s > 0 && ( l e f t == NULL | | pq .
c r o s s ( p o i n t ( c−>x , c−>y ) . s u b t r a c t ( p ) ) >

7.3 Kit de encolhimento - SBC 2016


Encontra a menor área de um polígono convexo os vértices são deslocados ou para o ponto médio de Ax ou Bx.

point operator +( p o i n t o t h e r ) {
#define i n f 0 x 3 f 3 f 3 f 3 f return p o i n t ( x+o t h e r . x , y+o t h e r . y ) ;
#define e p s 1 e −9 }
#define MAXN 100010 p o i n t operator / ( double v ) {
return p o i n t ( x/v , y/v ) ;
struct p o i n t { }
double x , y ; double operator ∗ ( p o i n t q ) {
p o i n t ( ) {} return x ∗ q . x + y ∗ q . y ;
p o i n t ( double a , double b){ }
x = a; double a n g l e ( ) {
y = b; return atan2 ( double ( y ) , double ( x ) ) ;
} }
point operator −( p o i n t o t h e r ) { void r e a d ( ) { s c a n f ( "%l f %l f " , &x , &y ) ; }
return p o i n t ( x−o t h e r . x , y−o t h e r . y ) ; };
}
CAPÍTULO 7. GEOMETRIA COMPUTACIONAL 41

double cross ( point p , point q) { return p . x ∗ q . y−p . for ( int i = 0 ; i < 2 ; i ++){
y∗q . x ; } int g o i n g = d i r e c t i o n ( medio [ id − 2 ] [ p e n u l ] ,
medio [ id − 1 ] [ u l t ] , medio [ i d ] [ i ] ) ;
double a = a r e a ( medio [ 0 ] [ f i r s t ] , medio [ id
bool cmp( p o i n t a , p o i n t b ) {
// Sort by angle with pivot
− 1 ] [ u l t ] , medio [ i d ] [ i ] ) ;
p o i n t p i v o t = p o i n t ( px , py ) ;
int x = d i r e c t i o n ( p i v o t , a , b ) ; if ( o r i
== 0 ) {
if ( x == 0 ) ans = min ( ans , a+s o l v e ( i d +1, u l t , i ,
return ( p i v o t −a ) ∗ ( p i v o t −a ) < ( p i v o t −b ) ∗ ( temArea | ( a>e p s ) , g o i n g ) ) ;
p i v o t −b ) ; }
return x==1; else if ( g o i n g == o r i | | g o i n g == 0 ) {
}
double c = c r o s s ( medio [ i d ] [ i ] − medio [ id
// Tratar casos de espiral

double d e t ( p o i n t a , p o i n t b , p o i n t c ) { − 1 ] [ u l t ] , medio [ 0 ] [ f i r s t ] − medio [ id


return ( a . x ∗ b . y ) + ( b . x ∗ c . y ) + ( c . x ∗ a . y ) −1][ ult ] ) ;
− (a . x ∗ c . y) − (b . x ∗ a . y) − ( c . x ∗ b . y) ; if( g o i n g == 0 )
double v a l = ( b . y−a . y ) ∗ ( c . x−b . x ) − ans = min ( ans , a+s o l v e ( i d +1, u l t , i ,
( b . x−a . x ) ∗ ( c . y−b . y ) ; temArea | ( a>e p s ) , o r i ) ) ;
return v a l ; else {
} if ( fabs ( c ) < eps )
ans = min ( ans , a+s o l v e ( i d +1, u l t , i ,
int d i r e c t i o n ( point a , point b , point c ) { temArea | ( a>e p s ) , o r i ) ) ;
double v a l = d e t ( a , b , c ) ; else if( g o i n g == 2 && c > 0 )
if ( f a b s ( v a l ) < e p s ) continue ;
return 0 ; else if( g o i n g == 1 && c < 0 )
return v a l > 0 ? 1 : 2 ; continue ;
else
// 0 Colinear , 1
Clockwise , 2 Counter
} ans = min ( ans , a+s o l v e ( i d +1, u l t , i ,
temArea | ( a>e p s ) , o r i ) ) ;
double a r e a ( p o i n t a , p o i n t b , point c ){ }
return f a b s ( d e t ( a , b , c ) ) ;
}
}
int n; }
p o i n t v [MAXN] ; return ans ;
p o i n t medio [MAXN] [ 2 ] ; }
p o i n t A, B ;
int main ( ) {
double dp [MAXN] [ 2 ] [ 2 ] [ 2 ] [ 3 ] ; s c a n f ( "%d" , &n ) ;
int v i s [MAXN] [ 2 ] [ 2 ] [ 2 ] [ 3 ] ; for int
( i = 0 ; i < n ; i ++)
int c n t ; v [ i ] . read ( ) ;
int f i r s t , s e c o n d ; A. r e a d ( ) ;
B. read ( ) ;
double s o l v e ( int id , int penul , int u l t , int
temArea , int o r i ) { for ( int i = 0 ; i < n ; i ++){
if ( i d == n ) { medio [ i ] [ 0 ] = ( v [ i ]+A) / 2 ;
int o1 = d i r e c t i o n ( medio [ id − 2 ] [ p e n u l ] , medio medio [ i ] [ 1 ] = ( v [ i ]+B) / 2 ;
[ id − 1 ] [ u l t ] , medio [ 0 ] [ f i r s t ] ) ; }
int o2 = d i r e c t i o n ( medio [ id − 1 ] [ u l t ] , medio
[ 0 ] [ f i r s t ] , medio [ 1 ] [ s e c o n d ] ) ; double ans = 1LL<<60;
// Tratar concavidade na hora de fechar o for ( int i = 0 ; i < 2 ; i ++){
first = i ;
if for ( int j = 0 ; j <
poligono
( o2 == 0 ) 2 ; j ++){
o2 = o1 ; second = j ;
if( o1 != o2 ) c n t++;
return 1LL<<60; for int
( k = 0 ; k < 2 ; k++){
if( o1 != 0 && o1 != o r i ) double a = a r e a ( medio [ 0 ] [ i ] , medio [ 1 ] [
return 1LL<<60; j ] , medio [ 2 ] [ k ] ) ;
if( temArea == 0 ) ans = min ( ans , a+s o l v e ( 3 , j , k , a >
return 1LL<<60; eps , d i r e c t i o n ( medio [ 0 ] [ i ] , medio
return 0; [ 1 ] [ j ] , medio [ 2 ] [ k ] ) ) ) ;
} }
double &ans = dp [ i d ] [ p e n u l ] [ u l t ] [ temArea ] [ o r i ] ; }
if ( v i s [ i d ] [ p e n u l ] [ u l t ] [ temArea ] [ o r i ] == c n t ) }
return ans ; p r i n t f ( "%.3 l f \n" , ans / 2 . 0 ) ;
v i s [ i d ] [ p e n u l ] [ u l t ] [ temArea ] [ o r i ] = c n t ; return 0;
ans = 1LL<<60; }

7.4 Intersecção círculo e segmento


CAPÍTULO 7. GEOMETRIA COMPUTACIONAL 42

_inline ( intcmp) ( double


x, double
y = 0, double
t o l = EPS) // Encontra o ponto do segmento mais proximo a C
{ point circle_closest_point_seg ( point p , point q ,
return ( x <= y + t o l ) ? ( x + t o l < y ) ? −1 : 0 circle c)
: 1; {
} point A = q − p , B = c . f i r s t − p ;
double abs ( p o i n t p ) doublep r o j = (A ∗ B) / abs (A) ;
{ if
(cmp( p r o j ) < 0 ) p; return
return hypot ( p . x , p . y ) ; if
(cmp( p r o j , abs (A) ) > 0 ) q; return
} return
p + (A ∗ p r o j ) / abs (A) ;
double arg ( point p) }
{
return
//
atan2 ( p . y , p . x ) ; ////////////////////////////////////////////////////
}
typedef p a i r <p o i n t , double
> circle ;
bool
// Decide se o segmento pq se interseca com c
seg_circle_intersect ( point p , point q , c i r c l e
bool i n _ c i r c l e ( c i r c l e C, p o i n t p ) c)
{ {
return cmp( abs ( p − C. f i r s t ) , C. s e c o n d ) <= 0; point r = circle_closest_point_seg (p , q , c ) ;
} return in_circle (c , r ) ;
}
//
////////////////////////////////////////////////////

7.5 Intersecção e distância entre segmentos


Código bem doido.

bool between ( const pu &a , const pu & b , const


typedef double co ; pu & c ) {
return ( c . x − a . x ) ∗ ( c . x −b . x ) <= 0 &&
( c . y−a . y ) ∗ ( c . y−b . y ) <= 0 ;
struct
// / g e o m e t r y
pu { }
co x , y ;
pu ( co a=0, co b=0) {x=a ; y=b ; } bool gr ( constpu &a1 , pu &a2 ,const pu & const
}; b1 , constpu &b2 ) {
pu operator −( const pu &a , const pu &b ) { co w1 = kr ( b1−a1 , a2−a1 ) , w2 = kr ( a2−a1 ,
return pu ( a . x−b . x , a . y−b . y ) ; b2−a1 ) ;
} if(w1 == 0 && w2 == 0 )
return between ( a1 , a2 , b1 ) | | between ( a1
bool operator==(const pu &a , const pu &b )
// Not always necessary !
{ , a2 , b2 ) | |
return a . x == b . x && a . y == b . y ; between ( b1 , b2 , a1 ) | | between ( b1 , b2 ,
} a2 ) ;
pu operator ∗ ( co a , const pu &b ) { return (w1 >= 0 && w2 >= 0 ) | | (w1 <= 0 && w2
return pu ( a ∗ b . x , a ∗ b . y ) ; <= 0 ) ;
} }

double operator ! ( const pu & a ) { bool i n t e r s e c t s ( const pu &a1 , const pu &a2 ,


return s q r t ( a . x ∗ a . x + a . y ∗ a . y ) ; const pu &b1 , const pu &b2 ) {
} return g r ( a1 , a2 , b1 , b2 ) && g r ( b1 , b2 ,
a1 , a2 ) ; ;
}
co kr ( const pu &a , const pu &b ) { // z component

return a . x ∗ b . y−b . x ∗ a . y ;
of the cross product $a \ t i m e s b$ // Pra baixo eh distancia entre segmentos

} bool comp ( double a , double b ){


co kr ( const pu &a , const pu &b , const pu &c ) { // return f a b s ( a − b ) > EPS ; //TODO < EPS?
z component of the cross product $ ( b−a ) \ t i m e s }

return struct P{
( c−a ) $
kr ( b−a , c−a ) ;
} double x , y ;
P( double x= 0 , double y = 0 ) : x ( x ) , y ( y ) {}
P operator + ( P i n ) { return P( x + i n . x , y +
// Intersection of the ( infinite ) lines $a_1a_2$
and $b_1b_2$ ( if they aren ' t parallel ) .
in . y ) ; }
P operator − ( P i n ) { return P( x − i n . x , y −
// You obviously have to use floating point

const pu &a1 , const pu &a2 , const pu &b1 ,


numbers , here !
pu i n t e r ( in . y ) ; }
const pu &b2 ) {
return ( 1 / kr ( a1−a2 , b1−b2 ) ) ∗ ( kr ( a1 , a2 ) ∗ ( b1−b2 ) − double operator ∗ ( P i n ) { return x ∗ i n . x +
kr ( b1 , b2 ) ∗ ( a1−a2 ) ) ; y ∗ in . y ; }
} P operator / ( P i n ) { double f = (P( x , y ) ∗ i n
) / ( i n ∗ i n ) ; return P( i n . x ∗ f , i n . y ∗ f ) ; }
CAPÍTULO 7. GEOMETRIA COMPUTACIONAL 43

double operator ! ( ) { return s q r t ( x∗x + y∗y ) return min ( ! ( a−c ) , ! ( b−c ) ) ;


; } }
};
double d i s t S S ( P a , P b , P c , P d ) {
pu go ( P & a ) { return pu ( a . x , a . y ) ; } if ( i n t e r s e c t s ( go ( a ) , go ( b ) , go ( c ) , go ( d ) ) )
return 0 ;
double d i s t S P (P a , P b , P c ) { return min ( min ( d i s t S P ( a , b , c ) , d i s t S P ( a , b , d ) ) ,
if ( ! comp ( a . x , b . x ) && ! comp ( a . y , b . y ) ) return min ( d i s t S P ( c , d , a ) , d i s t S P ( c , d , b ) ) ) ;
! ( c−a ) ; }
P pp = a + ( c−a ) / ( b−a ) ;
if( ! comp ( ! ( a−pp ) + ! ( pp−b ) , ! ( a−b ) ) ) return
! ( c−pp ) ;

7.6 Closest pair problem


O(nlogn).

while ( l e f t <i && p n t s [ i ] . px−p n t s [ l e f t ] . px >


#define px s e c o n d best )
#define py f i r s t box . e r a s e ( p n t s [ l e f t ++]) ;
typedef p a i r <long long , long long> p a i r l l ; for( t y p e o f ( box . b e g i n ( ) ) i t=box . lower_bound (
p a i r l l p n t s [MAX] ; make_pair ( p n t s [ i ] . py−b e s t , p n t s [ i ] . px−
int compare ( p a i r l l a , p a i r l l b ) { b e s t ) ) ; i t != box . end ( ) && p n t s [ i ] . py+b e s t
return a . px<b . px ; >=i t −>py ; i t ++)
} b e s t = min ( b e s t , s q r t ( pow ( p n t s [ i ] . py − i t
double c l o s e s t _ p a i r ( p a i r l l p n t s [ ] , int n ) { −>py , 2 . 0 )+pow ( p n t s [ i ] . px − i t −>px ,
s o r t ( pnts , p n t s+n , compare ) ; 2.0) ) ) ;
double b e s t=INF ; box . i n s e r t ( p n t s [ i ] ) ;
s e t <p a i r l l > box ; }
box . i n s e r t ( p n t s [ 0 ] ) ; return best ;
int l e f t = 0; }
for int( i =1; i <n;++ i ) {

7.7 Área de união de retângulo


Complexidade O(N 2 ), pode diminuir se colocar uma BST no lugar do array de booleano.

for ( int i =1; i <e;++ i )


#define MAX 1000 {
struct e v e n t {
// Vertical sweep line
e v e n t c = events_v [ i ] ;
int i n d ; int c n t = 0 ; // C o u n t e r
bool type ;
// Index of rectangle in rects to indicate how many
// Type of event : 0 = Lower− l e f t ; 1 rectangles are currently overlapping
= Upper− r i g h t // Delta_x : Distance between current sweep
event ( ) {};
int int int
line and previous sweep line
event ( ind , type ) : i n d ( i n d ) , type ( type ) delta_x = r e c t s [ c . i n d ] [ c . type ] . x − r e c t s
{}; [ events_v [ i − 1 ] . i n d ] [ events_v [ i − 1 ] . type ] .
}; x;
struct point { int begin_y ;
int x, y; if ( delta_x==0){
}; i n _ s e t [ c . i n d ] = ( c . type==0) ;
p o i n t r e c t s [MAX] [ 1 2 ] ; // Each rectangle consists continue ;
}
for ( int j =0; j <e;++ j )
of 2 points : [0] = lower−l e f t ; [1] = upper−

bool compare_x ( e v e n t a , e v e n t b ) { return r e c t s [ a . if ( i n _ s e t [ events_h [ j ] . i n d ]==1)


right

i n d ] [ a . type ] . x<r e c t s [ b . i n d ] [ b . type ] . x ; }


bool compare_y ( e v e n t a , e v e n t b ) { return r e c t s [ a .
// H o r i z o n t a l sweep line
for active rectangle
i n d ] [ a . type ] . y<r e c t s [ b . i n d ] [ b . type ] . y ; } {
int union_area ( e v e n t events_v [ ] , e v e n t events_h [ ] , if ( events_h [ j ] . type==0)
int n , int e ) { // I f it is a bottom edge of rectangle
{
if
// n is the number of rectangles , e =2∗n , e is
the number of points ( each rectangle has ( c n t==0) begin_y = r e c t s [ events_h [ j
two points as described in declaration of ] . i n d ] [ 0 ] . y ; // B l o c k s t a r t s
++c n t ;
bool int
rects ) //
i n _ s e t [MAX] = { 0 } ; a r e a =0; incrementing number of overlapping
s o r t ( events_v , events_v+e , compare_x ) ; // Pre− rectangles
}
else
sort of vertical edges
s o r t ( events_h , events_h+e , compare_y ) ; // Pre−
sort set of horizontal edges // I f it is a top edge
i n _ s e t [ events_v [ 0 ] . i n d ] = 1 ; {
CAPÍTULO 7. GEOMETRIA COMPUTACIONAL 44

−− c n t ; // t h e a r e a+=delta_x ∗ delta_y ;
rectangle is no more overlapping , }
}
if
so remove it
( c n t==0) // }
Block ends i n _ s e t [ c . i n d ] = ( c . type==0) ; // I f it is a
{
int
left edge , the rectangle is in the
delta_y = ( r e c t s [ events_h [ j ] . active set else not
i n d ] [ 1 3 ] . y−begin_y ) ; // l e n g t h o f }
the vertical sweep line cut by return area ;
rectangles }

7.8 Distância entre segmento e ponto


Distância entre segmento e ponto

double d i s t (P p , P a , P b ) {
operator −(P b ) { return P( x−b . x , y−b . y ) ; }
// P eh o ponto , a−b a
Point
double l e n ( ) { return hypot ( x , y ) ; } return c r o s s ( p−a , b−a ) / ( b−a ) . l e n ( ) ;
reta

double c r o s s (P a , P b ) { return a . x ∗ b . y−a . y ∗ b . x ; } }


Capítulo 8

Miscelânea
8.1 Datas
}
struct Date {
int d , m, y ; void advance ( int
days ) {
static int mnt [ ] , mntsum [ ] ; days += count ( ) ;
d = m = 1 , y = 1 + days / 3 6 6 ;
Date ( ) : d ( 1 ) , m( 1 ) , y ( 1 ) {} days −= count ( ) ;
Date ( int d, int
m, inty ) : d ( d ) , m(m) , y ( y ) {} while( days >= ydays ( ) ) days −= ydays ( ) , y++;
Date ( int days ) : d ( 1 ) , m( 1 ) , y ( 1 ) { advance ( while( days >= mdays ( ) ) days −= mdays ( ) , m++;
days ) ; } d += days ;
}
bool bissexto () { return ( y%4 == 0 and y%100) };
or ( y%400 == 0 ) ; }
int Date : : mnt [ 1 3 ] = { 0 , 3 1 , 2 8 , 3 1 , 3 0 , 31 , 30 ,
int mdays ( ) { return mnt [m] + (m == 2 ) ∗ b i s s e x t o 31 , 31 , 30 , 31 , 30 , 31};
() ; } int Date : : mntsum [ 1 3 ] = { } ;
int ydays ( ) { return 365+ b i s s e x t o ( ) ; } for ( int i =1; i <13; ++i ) Date : : mntsum [ i ] = Date : :
mntsum [ i − 1] + Date : : mnt [ i ] ;
int msum( ) { return mntsum [m− 1] + (m > 2 ) ∗
bissexto () ; }
int ysum ( ) { return int
// Week day
3 6 5 ∗ ( y − 1) + ( y − 1) /4 − ( y v [ ] = { 0 , 3 , 2 , 5 , 0 , 3 , 5 , 1 , 4 , 6 , 2 , 4 };
− 1) /100 + ( y − 1) / 4 0 0 ; } int int
day ( d, int
m, int
y) {
y −= m<3;
int count ( ) { return ( d − 1) + msum( ) + ysum ( ) ; } return ( y + y /4 − y /100 + y /400 + v [m− 1] + d )
%7;
int day ( ) { }
int x = y − (m<3) ;
return ( x + x /4 − x /100 + x /400 + mntsum [m
− 1] + d + 6 ) %7;

8.2 Hash C++11


hash<s t r i n g > hashFunc ;
c o u t << hashFunc ( " G a b r i e l " ) << e n d l ;

8.3 Mo's
Cada query em O(sqrt(N ).

}
#define MAXN 100100 };
int BLOCK;
int v i s [MAXN] , r e s p ;
// ~ s q r t (MAXN)

struct query {
int l , r , i d ; void add ( int i d ) {
bool operator <( const query f o o ) const { if ( ! v i s [ i d ] ) {
if ( l / BLOCK != f o o . l / BLOCK)
return l / BLOCK < f o o . l / BLOCK;
// Add element and update resp
}
return r < f o o . r ; else {
45
CAPÍTULO 8. MISCELÂNEA 46

for ( int i = 0 ; i < q ; i ++){


// Remove element and update resp
}
v i s [ i d ] ^= 1 ; int l = q u e r i e s [ i ] . l , r = q u e r i e s [ i ] . r ;
}
while ( curL < l ) add ( curL++) ;
while ( curL > l ) add(−−curL ) ;
int q ; while ( curR <= r ) add ( curR++) ;
// IN MAIN

sort ( queries , q u e r i e s+q ) ; while ( curR > r +1) add(−−curR ) ;


int ans [ q ] ; ans [ q u e r i e s [ i ] . i d ] = r e s p ;
int curL = 0 , curR = 0 ; }
resp = 0;

8.4 Problema do histograma


Maior retângulo do histograma em O(n).

tp = s . top ( ) ;
l l histograma ( l l vet [ ] , int
n){ s . pop ( ) ;
s t a c k <l l > s ; c u r = v e t [ tp ] ∗ ( s . empty ( ) ? i : i − s . top
l l ans = 0 , tp , c u r ; ( ) − 1) ;
int i = 0; if ( ans < c u r )
while ( i < n | | ! s . empty ( ) ) { ans = c u r ;
if ( i < n && ( s . empty ( ) | | v e t [ s . top ( ) ] <= }
vet [ i ] ) ) }
s . push ( i ++) ; return ans ;
else { }

8.5 Sliding Window - Mediana


Mediana de todas as janelas de tamanho K de um array O(nlog).

if ( i == nums . s i z e ( ) )
int k; break ;
vector< int
> nums ;
multiset< int
> window ( nums . b e g i n ( ) , nums . b e g i n ( ) + window . i n s e r t ( nums [ i ] ) ;
k) ; if( nums [ i ] < ∗ mid )
auto mid = next ( window . b e g i n ( ) , k / 2 ) ; mid −−;
for int
( i=k ; ; i ++) { if( nums [ i −k ] <= ∗ mid )
int janela = ( ) (( int double
( ∗ mid ) + ∗ prev ( mid , 1 mid++;
− k%2) ) / 2 ) ; // T r a t a n d o p a r e i m p a r window . e r a s e ( window . lower_bound ( nums [ i −k ] ) ) ;
}

Você também pode gostar