TFC 2020
Para conferir a prova na íntegra, clique aqui.
Transporte
Comentário escrito por Vitor Veiga
Conhecimento prévio necessário:
Dadas duas capacidades, máxima e mínima, de um trem e , queremos achar uma nova capacidade máxima tal que esta vale 30% de , e dizer se ela é maior que . Além disso, devemos remover as casas decimais de para realizar a comparação.
Sendo assim, basta calcular e depois checar se . Se for, retornamos , se não, retornamos . Note que poderiamos declarar como uma variável do tipo double e depois retirar as casas decimais utilizando a função floor(), porém, se declararmos como um int, o C++ automaticamente realiza a aproximação para o maior inteiro menor que o número decimal resultante da operação.
Clique aqui para conferir o código
Diária
Comentário escrito por Arthur Lobo
Conhecimento prévio necessário:
Já que a soma de todos os é menor do que , podemos criar uma lista que guardará quanto custa a diária em cada um dos dias. Sendo Sk o a soma de todos os , vamos criar um array , em que guardará quanto custa a diária do dia .
Para montar esse array, digamos que a soma dos até o blocos de dias é e já montamos a lista até esse bloco (até o dia ). Então se o bloco de dias tem tamanho e preço , então temos que fazer com que todos os valores de até sejam P, ou seja, , para , e em seguida aumentamos a soma dos fazendo .
Agora que já montamos a lista de quanto custa cada diária, sabemos que para responder uma consulta , ou seja, que pergunta qual vai ser o valor total das diárias se ficar hospedado do dia até o dia , devemos computar o valor de . Agora vamos para as parciais.
Vale ressaltar que se deve usar "long long" ao invés de "int" para computar a soma dos valores de . O único motivo pelo qual existem algumas parciais com é para caso alguém esqueça de usar long long.
Parcial 1 ()
Como nessa parcial nos temos poucas consultas, podemos responder cada uma delas em .Para uma consulta , primeiro inicializamos uma variável "int soma = 0", e então computamos a soma das diárias fazendo um for com indo de até , e fazendo . No final, a variável soma guardará .
A complexidade ficará por consulta, então no total é , que é o suficiente.
Parcial 2 ()
Nessa parcial, o da consulta é sempre , então só nos importamos com o , já que o que vamos querer computar é , ou seja, a soma de um prefixo da lista.
Para responder qual a soma de cada prefixo, vamos criar outro array , em que vai guardar a soma das diárias até , ou seja, , mas como computar esse novo array?
Perceba que sempre temos que , pois guardá e depois só adicionamos . Portanto, começamos com , e faremos um for com indo de até (nessa ordem), para cada , faremos , pois quando estamos em , já calculamos .
Agora, para responder uma consulta (já que ), basta imprimirmos . A complexidade fica de pré-processamento e para cada consulta, portando no total fica .
Parcial 3 e 4 (Sem restrições adicionais)
Diferente da parcial anterior, agora cada consulta vai pedir qual é o valor de , mas como podemos usar o array para nos ajudar a computar esse valor de forma rápida? Tente imaginar como saber a soma de cada prefixo pode nos ajudar a descobrir a soma desejada.
é , o problema é que queremos apenas . Podemos dividir essa soma que forma em 2 partes: , mas nós queremos apenas essa segunda parte. Perceba que essa primeira parte é exatamente , então para conseguirmos a soma desejada, podemos fazer , já que, como visto a cima, vai sobrar apenas a segunda parte da maneira que dividimos o .
Agora, para responder uma consulta , basta imprimirmos . A complexidade fica de pré-processamento e para cada consulta, portando no total fica , que é o suficiente.
Clique aqui para conferir o código
Robô
Comentário escrito por Caique Paiva e Enzo Dantas
Conhecimento prévio necessário:
Primeiro, vamos fazer a subtask 3, ou seja, . Nesse caso, a ideia é simples! Basta fazer uma matriz , e, supondo que estamos em , que é inicializada com , salvamos uma variável auxiliar , que vai contar a quantidade de obstáculos que já batemos, e dependendo da direção atual, fazemos o seguinte:
- Se estamos andando para a direita, então, se for um obstáculo, então mudamos a direção para baixo, e fazemos . Se não, faça .
- Se estamos andando para baixo, então, se for um obstáculo, então mudamos a direção para esquerda, e fazemos . Se não, faça .
- Se estamos andando para a esquerda, então, se for um obstáculo, então mudamos a direção para cima, e fazemos . Se não, faça .
- Se estamos andando para cima, então, se for um obstáculo, então mudamos a direção para direita, e fazemos . Se não, faça .
Se , então pare de rodar o código, então, a resposta será .
Perfeito! Agora, vamos melhorar essa solução. Primeiro, para o problema original, temos que , e então não conseguimos nem construir a matriz, pois se não vai dar MLE (Erro no Limite de Memória), então, vamos criar um vetor de set <int> linhas[] e um vetor de set <int> colunas []. Então, se tem um obstáculo em , fazemos e , e então, a ideia é ver que, se estamos na casa , então, nós vamos andar até chegamos na próxima parede, e aí viramos, ou seja, não precisamos andar as casa uma de cada vez. Logo, vamos mudar nossas condições que fizemos acima. Suponha que estamos em , que é inicializada com , temos que
- Se estamos andando para a direita, então, procuramos no set linhas[] qual é o primeiro obstáculo depois da casa e na mesma linha que , ou seja, qual é o primeiro em linhas[] com , e paramos de andar em , e então basta fazer , e , pois batemos em uma parede, e então viramos para baixo (Para achar esse valor, basta olhar o ponteiro linhas[].upper_bound()).
- As ideias são analogas para os outros casos. Se estamos andando para baixo, então, procuramos no set colunas[] qual é o primeiro obstáculo depois de , ou seja, qual é o primeiro em colunas[] tal que , e paramos de andar em , e então basta fazer e virar para esquerda (Para achar esse valor, basta olhar o ponteiro colunas[].upper_bound()).
- Se estamos andando para a esquerda, então, procuramos no set linhas[] qual é o primeiro obstáculo depois de , ou seja, qual é o primeiro em linhas[] tal que , e paramos de andar em , e então, faça e virar para cima (Para achar esse valor, basta olhar o ponteiro linhas[].upper_bound() e voltar o ponteiro uma vez).
- Se estamos andando para cima, então, procuramos no set colunas[] qual é o primeiro obstáculo depois de , ou seja, qual é o primeiro em colunas[] tal que , e paramos de antar em , e então, faça , e vire para a direita (Para achar esse valor, basta olhar o ponteiro colunas[].upper_bound(), e voltar o ponteiro uma vez).
Clique aqui para conferir o código
Sobrinhos
Comentário escrito por Enzo Dantas
Conhecimento prévio necessário:
Primeiramente vamos criar um array com os restos de cada pessoa. Mais especificamente, vamos criar um array e dizer que , tal que % é a função que retorna o resto da divisão entre e . Em seguida vamos ordenar esse array em ordem crescente usando a função . Finalmente, a resposta será o k-ésimo elemento desse array.