Problema D - Colónia de Formigas

Este é um problema de interação.
Ao contrário dos outros problemas em que deves fazer leitura de dados e escrita do output, neste problema deves interagir com o avaliador através da implementação de uma função e da interação com as funções fornecidas.

O Pedro tem uma colónia de formigas, que consiste em N apartamentos em linha númerados de 0 a N - 1. Cada apartamento contém um conjunto de formigas, sendo que o i-ésimo contém Ai formigas, valor esse que o Pedro desconhece. O seu irmão mais novo Gonçalo está muito curioso sobre a colónia de formigas e decide começar a fazer I perguntas ao seu irmão, sendo a i-ésima: dado um intervalo [Li, Ri] qual o máximo de formigas num único apartamento desse intervalo de posições. Como o Gonçalo queria muito saber as respostas, o Pedro construiu uns mini-robots para contar formigas, usando os seus conhecimentos adquiridos nas ONI. No entanto, sempre que ele manda k robots investigar a colónia, depois destes completarem a sua missão, são abandonados no meio da colónia. Seja Bi o número de robots abandonados no apartamento i, que no início é 0.

O Pedro pode enviar no máximo K robots investigar a colónia. Assim, sempre que o Pedro manda k dos seus robots investigar a colónia, estes calculam o valor da função maxFormigas(l, r, k), que devolve o máximo de k*Ai + Bi, com i contido no intervalo [l, r] fornecido, mas em contrapartida, adiciona alguns robots à colónia assim que devolve a resposta. Em particular, se k > r-l (se enviar mais robots do que apartamentos no intervalo), um robot é adicionado a cada apartamento em [l, r], caso contrário, os k robots são distribuidos de forma arbitrária pelos apartamentos em [l, r], sendo que nenhum destes fica com mais do que um robot novo. Por outras palavras, aplicamos Bi += 1 a todo o i no intervalo [l, r] se k > r-l ou a k apartamentos arbitrários distintos caso contrário.

Nota que o valor de k é no mínimo 0 (e neste caso nenhum robot é enviado e nenhum robot é perdido) e no máximo K (um inteiro positivo), não existe mais nenhuma restrição a este valor (ou seja, podes assumir que após perder alguns robots, o Pedro pode sempre construir mais para as próximas investigações).

O teu objetivo é ajudar o Pedro a responder às I perguntas do Gonçalo da forma indicada acima, utilizando a função maxFormigas que é executada pelos robots construídos pelo Pedro. Como o Gonçalo é incapaz de se acalmar depois de fazer uma pergunta, só faz uma pergunta nova depois de obter uma resposta. Como o Gonçalo é muito impaciente, o Pedro só pode realizar no máximo Q investigações por pergunta do irmão, ou seja, chamar a função maxFormigas Q vezes.

O Problema

Dado o número de apartamentos N e um conjunto de I intervalos, calcular para cada intervalo o máximo de A usando apenas a função maxFormigas(l, r, k) com k no máximo um dado K e chamando-a no máximo Q vezes por intervalo.

Ficheiros para Download

Podes começar por descarregar os ficheiros correspondentes à tua linguagem (ou um arquivo zip contendo tudo):

Linguagem Ficheiro a implementar Ficheiro com avaliador exemplo Ficheiros auxiliares Input para avaliador exemplo
C resolver.c avaliador.c avaliador.h input.txt
C++ resolver.cpp avaliador.cpp

Nota que a implementação do avaliador a usar nos testes oficiais será diferente, mas podes esperar o mesmo comportamento. Além disso, é garantido que o avaliador implementa a função maxFormigas em O(r - l).

Implementação

Deves submeter um único ficheiro que implementa duas funções:

Para isso deves usar o ficheiro resolver.{c,cpp} que descarregaste, colocando no interior das funções o teu código. Podes acrescentar outras funções, mas devem ficar todas neste ficheiro que é o único que deves submeter.

Funções a implementar:

C/C++: void iniciar(int N, int I, int K, int Q);
C/C++: long long int pergunta(int L, int R);

A tua função deve invocar a seguinte função:

Nota o seguinte:

Funções do avaliador:

C/C++: long long int maxFormigas(int l, int r, int k);

A tua função não deve ler nem escrever para os canais de entrada/saída padrão.

Exemplo

Vamos supor que há N = 5 apartamentos e que a colónia é representada pelo seguinte array: [2 1 6 3 1].

Uma possível execução seria a seguinte (com a ordem das chamadas a ser de cima para baixo):

Invocação Chamada avaliador Descrição
iniciar(5, 3, 5, 5) Inicialização. N=5, I=3, K=5, Q=5
pergunta(0, 3) O Gonçalo pergunta o máximo entre 0 e 3.
maxFormigas(0, 3, 1) Chamamos maxFormigas com l=0, r=3, k=1, o resultado é 6, vamos supor que B é agora [0 0 1 0 0]
retornar 6 Respondemos 6 à pergunta [0, 3], corretamente.
pergunta(1, 2) O Gonçalo pergunta o máximo entre 1 e 2.
maxFormigas(1, 2, 2) Chamamos maxFormigas com l=1, r=2, k=2, o resultado é 13 (2*6+1), vamos supor que B é agora [0 1 2 0 0]
retornar 6 Respondemos 6 à pergunta [1, 2], corretamente.
pergunta(3, 4) O Gonçalo pergunta o máximo entre 3 e 4.
maxFormigas(3, 4, 1) Chamamos maxFormigas com l=3, r=4, k=1, o resultado é 3, vamos supor que B é agora [0 1 2 0 1]
retornar 3 Respondemos 3 à pergunta [3, 4], corretamente.

Restrições

São garantidos os seguintes limites em todos os casos de teste:
1 ≤ N ≤ 5 000 Número de apartamentos.
1 ≤ I ≤ 5 000 Número de perguntas.
1 ≤ K ≤ 5 000 Número máximo de robots a enviar numa investigação.
1 ≤ Q ≤ 5 000 Número máximo de investigações por intervalo.
0 ≤ Ai ≤ 1 000 000 000 Número de formigas por apartamento.

Os valores de K, de robots a enviar numa investigação, assim como os valores de Q, máximo investigações por intervalo, são dados na secção seguinte.

Avaliação e Casos de Teste

Os casos de teste deste problema estarão agrupados em conjuntos de testes. Ao contrário dos restantes problemas, para obter pontuação é necessário acertar todos os casos de teste de um grupo de casos, nesse caso terão a pontuação completa relativa a esse grupo. Se falharem um ou mais casos de um grupo, a pontuação atribuída relativa a esse grupo será nula.

Cada grupo tem um número de pontos associado e um conjunto de restrições adicionais. Os grupos são os seguintes:

Grupo Número de Pontos Restrições adicionais
1 10 K = 5 000, Q = 5 000
2 10 K = 5 000, Q = 300
3 10 K = 20, Q = 300
4 20 K = 1, Q = 300
5 20 K = 1, Q = 180
6 30 K = 1, Q = 50

Testes no vosso computador

É disponibilizado um avaliador exemplo em cada linguagem (avaliador.{c,cpp}) que pode ser utilizado para testar a tua submissão. Está ainda disponível um ficheiro auxiliar (avaliador.h). Este avaliador não corresponde ao utilizado pelo sistema de avaliação.

Este avaliador começa por receber como input um inteiro N, um inteiro I, um inteiro K e um inteiro Q, correspondendo, respetivamente, ao número de apartamentos, ao número de perguntas, número máximo de robots a enviar numa investigação e ao número máximo investigações por intervalo. Segue-se uma linha com N inteiros não negativos, representando os valores de Ai. Seguem-se I linhas, uma para cada pergunta, cada uma com 2 inteiros L e R, separados por espaços, representando uma pergunta a responder.

O avaliador irá automaticamente invocar a função iniciar(N,I,K,Q), por vocês implementada, uma vez, e invocará seguidamente a função pergunta(L, R) I vezes, uma para cada intervalo. O avaliador indicará se a resposta é considerada correta ou não.

Disponibilizamos um ficheiro de teste:

Um exemplo de teste na tua máquina (supondo que tens os compiladores oficiais instalados) seria o seguinte:

Linguagem Compilar Executar com o exemplo
C gcc -Wall avaliador.c resolver.c ./a.out < input.txt
C++ g++ -Wall avaliador.cpp resolver.cpp ./a.out < input.txt

Prova de Seleção para as IOI'2019
Departamento de Ciência de Computadores
Faculdade de Ciências da Universidade do Porto
(9 de Junho de 2019)