Escolar Documentos
Profissional Documentos
Cultura Documentos
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
Introdução
1.1 Template
Digitar o template no inicio da prova.
NÃO esquecer de remover o f reopen()
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.
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.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
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).
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 ;
O(Qlog 2 N ).
#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 ) ;
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 ) ;
}
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 ) {
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
2.11 Kd-Tree
Encontra os K pontos mais próximos de um dado ponto O(klog(k)log(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
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 };
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
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
}
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;
} }
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 −−; };
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).
4.3 Dinic
Encontra o uxo máximo em O(V 2 E).
22
CAPÍTULO 4. GRAFOS 23
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 ;
4.6 Tarjan
Componentes fortemente conexos em O(V + E).
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 ;
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 ) ;
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) >.
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
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 ; }
} }
// 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! }
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
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){ }
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;
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;
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 ++){
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; }
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
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 ()
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).
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;
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
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
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
−− 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 }
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
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.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
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 { }
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 ] ) ) ;
}