OBI 2023 – Fase 2 – Turno B – Programação Nível Júnior
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 os nossos materiais.
Para conferir a prova na integra, entre no site da OBI.
UPA
Comentário escrito por Estela Baron
Conhecimento prévio necessário:
Observe o que o enunciado quer saber o maior espaço destinado aos ônibus, ou seja, queremos saber qual é a maior quantidade de veículos que coexistirão. Para isso, vamos dar uma olhada nas subtarefas.
Subtarefa 1:
Quando a tarefa define que
, temos que o ônibus só ocupa a posição
, ou seja, só precisamos nos preocupar com um ponto. Portanto, basta criarmos um vetor que guarda os instantes e adicionarmos +1 para cada
. Ao final, queremos saber o maior valor, pois indica a coexistência da quantidade máxima de veículos daquele momento/ponto. Lembre de multiplicar por 20.
Subtarefa 2:
A partir da tarefa 2, passamos a lidar com intervalos, então a nossa ideia anterior não funciona. Porém, como o
e
são menores ou iguais a
, podemos criar um vetor de instantes que guarda a quantidade de ônibus presentes no instante[i]. Com isso podemos adaptar a ideia da tarefa anterior: para todo instante compreendido de
e
, adicionamos +1. Da mesma forma, temos que armazenar a maior resposta (podemos criar uma variável que guarda o maior valor e ir atualizando), e multiplicá-la por 20. A complexidade fica
. Como
<= 1000, então passa no limite do tempo.
Subtarefa 3:
Observe que, na teoria, não passaria no tempo aplicar a ideia da sub2 nessa tarefa. No entanto, como nos é garantida que a resposta é no máximo 1000, podemos inferir que temos no máximo
ônibus coexistindo. Ou seja, se analisarmos o nosso vetor de instantes, teríamos que o valor máximo seria
. Portanto, só visitaríamos no máximo 50 vezes cada posição. Com isso, a nossa complexidade ficaria
=
.
Subtarefa 4 – Solução 1:
No intuito de conseguir lidar com valores grandes de
e de não depender de uma resposta máxima definida, podemos utilizar a técnica da soma de prefixos. Basicamente, é a mesma ideia da subtarefa 2, no entanto, em vez de ir adicionando um por um no intervalo, vamos adicionar +1 no
e adicionar -1
. Ao fazer a soma acumulada, cada posição será somada ao valor da anterior. Com isso, o +1 do
irá se “propagar” até o final do intervalo. Contudo, como também tem o -1, também propagamos o -1 do
até o final, observe que o +1 e o -1 irão resultar em 0, o que possibilita a soma do +1 do
até o
– no instante
, o ônibus já saiu.
Resumindo, para cada ônibus, iremos adicionar +1 em
e -1 em
. Depois de ter processado todos os veículos, iremos fazer a soma acumulada: adicionar o valor do instante[i-1] ao instante[i]. Em cada instante, teremos a quantidade de ônibus estacionados naquele tempo. Por fim, basta guardar o maior valor encontrado e multiplicar por 20. A complexidade fica
.
Subtarefa 4 – Solução 2:
Outra solução possível é, para cada ônibus, adicionar em um vetor um par com: o instante da entrada e o valor +1 – indicando que o ônibus novo entrou no estacionamento- e um outro par com : o instante da partida e o valor -1 – indicando que o ônibus saiu. Depois de ter colocado todos os valores dos
veículos, vamos ordenar o vetor em ordem crescente do instante.
Com isso, vamos percorrer o vetor e vamos criar uma variável para guardar a quantidade de veículos. Toda vez que o instante indica a entrada de algum ônibus, vamos adicionar +1 na quantidade e ,toda vez que algum ônibus sai, vamos adicionar -1 na quantidade. Com isso, conseguimos ter a quantidade de veículos no estacionamento entre cada “evento novo” (chegada ou saída). De novo, vamos guardar o maior valor da quantidade e multiplicar por 20. Complexidade:
.
Clique aqui para conferir a solução 1 e a solução 2.
Empresa
Comentário escrito por João Pedro Castro
Conhecimento prévio necessário:
Podemos visualizar a hierarquia dessa empresa como um grafo, onde os vértices (funcionários) tem outros vértices se ligando à ele (os subordinados). Além da estrutura do grafo, para cada funcionário vamos guardar seu chefe, salário, e a quantidade de subordinados com os quais ele está insatisfeito. Também é necessário guardar a quantidade de funcionários insatisfeitos no total, chamaremos esse valor de
.
Após montar o grafo (feito com as arestas sendo:
), receber o chefe de cada um e o salário, para preencher a quantidade de insatisfações basta percorrer o grafo começando do vértice 1 e aumentando o valor de
em uma unidade toda vez que
em 1 caso
, já que o estado do
vai mudar de satisfeito para insatisfeito.
Para todo funcionário
atualizado a ideia é checar se o “estado” (satisfeito ou insatisfeito) de seu chefe e dele mesmo (em relação ao seus subordinados) foram alterados, já que eles são os únicos com os quais isso pode ter acontecido. E isso pode ser feito com uma série de estruturas condicionais, que se resumem à:
- (chefe insatisfeito antes com o funcionário) e (chefe satisfeito agora)
- (chefe satisfeito antes com o funcionário) e (chefe insatisfeito agora)
Agora, para achar o valor de
(a resposta) atualizado, é só seguir o seguinte algoritimo:
- Se
![i \neq 1 ~\&~ salario[i] \geq salario[chefe[i]] ~\&~ novoSalario > salario[chefe[i]]” /></span><script type='math/tex'>i \neq 1 ~\&~ salario[i] \geq salario[chefe[i]] ~\&~ novoSalario > salario[chefe[i]]</script>
<ul>
<li><span class='MathJax_Preview'><img data-recalc-dims=](https://i0.wp.com/noic.com.br/wp-content/plugins/latex/cache/tex_d7de344477018121d4b63a1428c1884f.gif?ssl=1)
- Se
(novo chefe insatisfeito):
![salario[i] > salario[chefe[i]] ~\&~ salario[chefe[i]] \geq novoSalario” /></span><script type='math/tex'>salario[i] > salario[chefe[i]] ~\&~ salario[chefe[i]] \geq novoSalario</script>
<ul>
<li><span class='MathJax_Preview'><img data-recalc-dims=](https://i0.wp.com/noic.com.br/wp-content/plugins/latex/cache/tex_80ec85dbf53c940e881c03bd7b41cdc2.gif?ssl=1)
(chefe satisfeito de novo):
de
:
- Se
![salario[i] \geq salario[u] ~\&~ salario[u] > novoSalario” /></span><script type='math/tex'>salario[i] \geq salario[u] ~\&~ salario[u] > novoSalario</script>:
<ul>
<li><span class='MathJax_Preview'><img data-recalc-dims=](https://i0.wp.com/noic.com.br/wp-content/plugins/latex/cache/tex_5b97a6ce85bae54d5d10544b45d6792a.gif?ssl=1)
- Se
(novo chefe insatisfeito):
![salario[u] > salario[i] ~\&~ novoSalario \geq salario[u]” /></span><script type='math/tex'>salario[u] > salario[i] ~\&~ novoSalario \geq salario[u]</script>:
<ul>
<li><span class='MathJax_Preview'><img data-recalc-dims=](https://i0.wp.com/noic.com.br/wp-content/plugins/latex/cache/tex_701a52570f0ddc3850d70b186b7a1853.gif?ssl=1)
(chefe satisfeito de novo):
![salario[i] = novoSalario](https://i0.wp.com/noic.com.br/wp-content/plugins/latex/cache/tex_a0c9b38ee9310606014ff97dcddcf990.gif?ssl=1)

Assim você também garante que os valores de
e
sempre permanecem atualizados. Segue a solução em C++:
Brincadeiras de Roda
Comentário escrito por Enzo Dantas
Conhecimento prévio necessário:
Imagine um círculo com 5 pessoas. Se o professor bate palma 5 vezes, percebemos que todas as pessoas dão uma volta completa e continuam no mesmo lugar, e percebemos que isso também vale para qualquer número múltiplo de 5. Sendo assim, em um círculo com
pessoas, vamos nos importar apenas com a quantidade de palmas
módulo
. É fácil ver que uma pessoa qualquer que começa na posição
vai terminar aproximadamente na posição
. Trabalhando com casos pequenos chegamos na fórmula exata
, e essa é a solução em
.
Além disso, os limites pequenos do problema permitem uma solução ainda mais direta: simular cada palma do professor. Se a posição atual é igual a
, então a posição depois da palma é 1. Caso contrário apenas adicionamos 1 à posição. Complexidade: O(P).


