Simulado OBI 2023 – Fase 1 – Programação Nível 2
Se você quiser se preparar para a OBI, não deixe de conferir o Roteiro de estudos de informática, e também a página de informática do NOIC, com todos nossos materiais.
Para conferir a prova na íntegra, clique aqui.
Trio de Nerds
Comentário escrito por Vitor Veiga
Conhecimento prévio necessário:
O problema nos dá 3 strings, que representam os instrumentos tocados por Luca, Leo e Lúcio, e quer saber essas strings são “violao”, “piano” e “bateria”, em qualquer ordem.
Nossa estratégia de resolução será declarar 3 variáveis booleanas
, que começam sendo falsas. Enquanto lemos a entrada, checar se cada uma das strings de entrada representa alguma das strings alvo. Caso representem, marcamos como verdadeira a booleana do respectivo instrumento.
Se no final todas as booleanas estiverem marcadas, todos os instrumentos estão presentes e retornamos “S”. Caso contrário, retornamos “N”.
Outra maneira de resolver é ler as 3 strings em
e chegar se elas são todas diferentes entre si, ou seja,
,
e
.
Clique aqui para conferir o código
Atacante Devedor
Comentário escrito por Arthur Lobo
Conhecimento prévio necessário:
Sabemos quantos reais foi emprestado para cada amigo e quantos reais cada amigo nos emprestou, e nosso objetivo é saber o quanto nós temos que pagar os amigos para quitar a dívida, e quantos nossos amigos tem que nos pagar para que a dívida deles seja quitada.Primeiramente, começamos com duas variáveis
, representando quanto Leonardo deve pagar, e
, representando quando ele pagará.
Em seguida, faremos um for com
de
até
e, para cada
, analisaremos 3 casos:
.
: Isso significa que o atacante emprestou menos dinheiro para o amigo do que o amigo para ele, então o quanto ele paga aumenta em
.
: Nada acontece.
No fim, basta imprimir o valor de
e
.
Clique aqui para conferir o código
Banda de Nerds
Escrito por Caique Paiva
Conhecimento prévios necessário:
Vamos fazer um map de strings para vectors de inteiros, onde o
guarda as habilidades dos músicos que tocam o instrumento
. Vamos olhar para o sample para ficar mais claro
7 1
violao 3
guitarra 2
bateria 4
violao 3
violao 8
guitarra 3
piano 4
Então, montando o map dito acima, os valores vão ser os seguintes
violao![] = \{ 3, 3, 8 \}](https://i0.wp.com/noic.com.br/wp-content/plugins/latex/cache/tex_e5aab17802dddb1811f4f55f4eafd264.gif?ssl=1)
guitarra![] = \{ 2, 3 \}](https://i0.wp.com/noic.com.br/wp-content/plugins/latex/cache/tex_1797a0506e476f7de004463a6bfe8a32.gif?ssl=1)
bateria![] = \{ 4 \}](https://i0.wp.com/noic.com.br/wp-content/plugins/latex/cache/tex_3f768827a30024c999637b5edeb11f4f.gif?ssl=1)
piano![] = \{ 4 \}](https://i0.wp.com/noic.com.br/wp-content/plugins/latex/cache/tex_3f768827a30024c999637b5edeb11f4f.gif?ssl=1)
Então, para resolver o problema, vamos ordenar todos os vetores em ordem decrescente, e somar os
primeiros de cada um dos vetores, e essa soma vai ser a resposta do nosso problema.
Clique aqui para conferir o código
(Um detalhe importante do código é que, a soma final pode ser um valor muito grande, já que
e
, e fazendo uma estimativa simples, a gente tem que o valor da soma pode ser
, que passa do limite de inteiro, ou seja, temos que usar long long int. Veja que, no código colocado acima, eu coloco #define int long long, isso faz com que todo int vire long long, resolvendo o nosso problema)
Danoninho
Escrito por Enzo Dantas
Solução 1
Conhecimento prévio necessários:
Esse é um problema clássico de two pointers e a solução funciona da seguinte maneira: olhando para o intervalo
:
1) Se o valor desse intervalo é maior que
, então diminua-o aumentando o
em 1.
2) Se o valor desse intervalo é menor ou igual a
, então uma resposta possível é o seu tamanho
e aumentamos o intervalo aumentando o
.
A resposta é o maior segmento válido encontrado.
Para saber a soma do segmento a qualquer momento, basta adicionar/subtrair o valor de
/
toda vez que o
/
mudar de posição.
Complexidade: 
Clique aqui para conferir o código
Solução 2
Conhecimento prévios necessário:
Perceba que podemos fazer uma busca binária na resposta, ou seja, no tamanho do intervalo. Assuma que o tamanho do intervalo é
: vamos testar todos os intervalos de tamanho
e verificar se algum deles é válido, ou seja, possui valor menor ou igual a
. Se nenhum intervalo válido de tamanho
foi encontrado, então a resposta é menor que
. Caso algum tenha sido encontrado, dizemos que uma possível resposta é
e tentamos aumentar o tamanho.
Um outro jeito de visualizar isso é da seguinte maneira: sendo
a resposta, encontraremos um intervalo válido de qualquer tamanho menor ou igual a
, mas não encontraremos nenhum intervalo válido para um tamanho maior que
. Ou seja, é uma função monotônica na qual podemos fazer uma busca binária para achar o maior valor que é válido.
Para testar se existe um intervalo válido de um certo tamanho, basta percorrer todos os intervalos desse tamanho. Mais especificamente, se estou em um intervalo
de tamanho
, para testar o próximo intervalo de tamanho
basta subtrair
e adicionar
, e faço isso enquanto
(0-indexado). Essa técnica é conhecida como "sliding window", que é uma variação mais simples de two pointers.
Complexidade: 
