Entrada e Saída de Alto Desempenho
por Frank de Alcantara em 30/09/2026
- 1. Contar Antes de Programar: Complexidade, Restrições e Medição
- 2. A Máquina por Baixo do Algoritmo: Tipos, Cache e Desvios
- 3. Treino T01: Contando Antes de Codificar
- 4. Caixa de Ferramentas I: Tipos, Números e Trabalho em Tempo de Compilação
- 5. Caixa de Ferramentas II: Vetores, Matrizes, Vistas e Algoritmos
- 6. Treino T02: Pagar Uma Vez, Perguntar Sempre
- 7. Entrada e Saída de Alto Desempenho
- 8. Treino T03: Alimentando a Máquina
- 9. Busca Binária: Comprar Informação pela Metade
- 10. Ordenar por Comparação: o Limite, a Biblioteca e a Seleção
- 11. Ordenar sem Comparar: Contagem, Radix e a Escolha da Ferramenta
- 12. Treino T04: Comprar Informação
- 13. Somas de Prefixo e Arrays de Diferenças: Integrar e Derivar em Tempo Constante
- 14. Janelas que Deslizam: Deque Monotônico, Dois Ponteiros, Kadane e Sparse Table
- 15. Bits como Conjuntos: Máscaras, popcount e Bitsets de Muitas Palavras
- 16. Hash de Prefixo, Seleção em Três Partes e o Algoritmo de Mo
- 17. Treino T05: Intervalos com Orçamento
- 18. Pilhas, Filas, Heaps e Contêineres Associativos: o Estado que Sobrevive à Pergunta Seguinte
Um algoritmo std::cin. A análise assintótica estava certa, a implementação estava certa, e o gargalo entrou pela porta da frente, carregando espaços em branco.
Este artigo trata a entrada e a saída como parte do projeto do algoritmo. O percurso desce por camadas: primeiro, os fluxos da biblioteca padrão com as duas configurações obrigatórias; depois, a leitura e a escrita com buffer (área intermediária de memória) próprio, feitas com fread e fwrite; em seguida, arquivos com nome, com std::expected para os erros e std::string_view para analisar sem copiar; por fim, arquivos mapeados na memória e entrada e saída assíncronas. A ordem é deliberada. Começamos pela interface mais clara e só descemos quando a carga de trabalho paga pela descida. Código rápido não é o código que usa a interface de mais baixo nível disponível. É o código que gasta complexidade onde o gargalo realmente está.
Todas as medições deste artigo foram feitas com o MSVC do Visual Studio 18.10.3, com /std:c++latest /O2, em um Intel Core i7-10750H, com a entrada e a saída redirecionadas para arquivos, como em um juiz. Cada forma de leitura ou escrita rodou em um processo separado, porque as configurações dos fluxos valem para o processo inteiro, e os tempos são medianas de cinco execuções depois de uma de aquecimento. A maioria dos juízes online usa o GCC em Linux, e onde o comportamento do MSVC difere do comportamento do GCC, o texto diz.
1. As duas linhas obrigatórias
Toda solução comum que lê com std::cin deveria começar com duas linhas:
1
2
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
A primeira linha desliga a sincronização entre os fluxos do C++ e a biblioteca de entrada e saída do C. Por padrão, std::cin e std::cout ficam sincronizados com stdin e stdout, porque um programa pode misturar std::cin com scanf, ou std::cout com printf, e a ordem dos caracteres precisa sair certa. Essa compatibilidade tem um custo em cada leitura e em cada escrita: sincronizados, os fluxos do C++ não podem manter um buffer próprio e passam cada caractere pela biblioteca do C.
Este artigo completo contém estratégias práticas e dados exclusivos reservados para nossos membros cadastrados.
Continuar com Google Acesso gratuito e instantâneo com sua conta Google(Updated: )