Solução Informática – Nível Intermediário – Semana 20

por

Solução por Anita Ramos

Esse é um típico problema em que é necessário ter uma ideia sólida antes de programar e iniciar os testes. Essa ideia é bem simples, mas pode gerar uma certa confusão para conseguir “cobrir” todas as possibilidades.

A ideia consiste em já determinar o número de intervalos de cada número existentes na faixa logo na leitura inicial desta e, posteriormente, a cada pergunta em que $$num=1$$ atualizamos o número de intervalos de cada valor. O primeiro processo citado é simples, bastando comparar o valor da casinha lido com o valor da casinha anterior. O segundo é o que pode gerar uma certa confusão e uma dificuldade em esclarecer as possibilidades e, por isso, irei dividir em 4 opções, sendo que a escolha de uma opção não impede a escolha de outra, ou seja, mais de uma opção pode ser verdadeira, sendo assim, as duas serão executadas em ordem:

  1. Se os dois vizinhos da casinha $$X$$ forem iguais à $$C$$, subtrai-se 1 na quantidade de intervalos de valor igual a $$C$$, pois teremos a união de dois intervalos distintos -> a direita de $$X$$ e a esquerda de $$X$$ (não consideramos o valor da casinha $$X$$, pois ele será analisado depois);
  2. Se os dois vizinhos da casinha $$X$$ forem diferentes de $$C$$, soma-se 1 na quantidade de intervalos de valor igual a $$C$$, pois teremos a criação de um novo intervalo de um número “isolado” (diferente dos vizinhos);
  3. Se os dois vizinhos da casinha $$X$$ têm valores iguais ao valor ATUAL (sem alteração ainda) da casinha $$X$$, soma-se 1 na quantidade de intervalos de valor igual ao valor ATUAL da casinha $$X$$, pois teremos a separação de 1 intervalo em dois intervalos (desconsiderando o novo valor $$C$$ da casinha $$X$$);
  4. Se os dois vizinhos da casinha $$X$$ têm valores diferentes do valor ATUAL (sem alteração ainda) da casinha $$X$$, subtrai-se 1 na quantidade de intervalos de valor igual ao valor ATUAL da casinha $$X$$, pois teremos que o intervalo desse número isolado da casinha $$X$$ sumirá ao trocarmos seu valor.

Assim, o truque está em considerar o que ocorrerá inicialmente (casos 1 e 2 acima) independente do valor ATUAL da casinha $$X$$, pois basta considerar ambos os casos posteriormente (casos 3 e 4). Depois de uma pergunta com $$num=1$$, não podemos esquecer de, ao final, atualizar o valor da casinha $$X$$ ($$v[X] = C$$).

O terceiro e último processo é se $$num=2$$, em que imprimimos o valor de $$marc[C]$$ (número de intervalos da cor/número $$C$$).

Segue o código comentado para melhor compreensão da solução:


#include<bits/stdc++.h> //biblioteca utilizada
using namespace std;
const int MAXN=10000000; //define MAXN como 10000000
int marc[MAXN]; //declaro um vetor de marcação de tamanho 'MAXN'
int main()
{
int N,Q,X,C,num; //declaração de variáveis
scanf("%d %d", &N, &Q); //leitura da 1º linha de entrada
int v[N+1]; //declaro um vetor de tamanho 'N'+1
for(int i=1; i<=N; i++) //loop para ler toda a fita
{
scanf("%d", &v[i]); //leitura dos valores da fita
if(v[i-1]!=v[i])marc[v[i]]++; //se o valor casinha da fita atual é diferente do valor da anterior, soma-se 1 ao vetor de marcação dessa cor (valor da casinha)
}
for(int i=1; i<=Q; i++) //loop para ler todas as "perguntas"
{
scanf("%d", &num); //lê o 1º número da pergunta (1 ou 2)
if(num==1) //se for 1
{
scanf("%d %d", &X, &C); //lê 'X' e 'C'
if(v[X+1]==C && v[X-1]==C)marc[C]–; //se os dois vizinhos da casinha 'X' são iguais a 'C', subtrai 1 na qntd de intervalos de 'C' (união de dois intervalos distintos)
if(v[X+1]!=C && v[X-1]!=C)marc[C]++; //se os dois vizinhos da casinha 'X' são diferentes de 'C', soma 1 na qntd de intervalos de 'C' (número isolado = novo intervalo)
if(v[X+1]==v[X] && v[X-1]==v[X])marc[v[X]]++; //se os dois vizinhos da casinha 'X' são iguais à casinha 'X', soma 1 na qntd de intervalos do valor da casinha 'X' (separação de um intervalo contínuo = 2 intervalos separados)
else if(v[X+1]!=v[X] && v[X-1]!=v[X])marc[v[X]]–; //se os dois vizinhos da casinha 'X' são diferentes da casinha 'X', subtrai 1 na qntd de intervalos do valor da casinha 'X' (intervalo de um número isolado = intervalo some)
v[X]=C; //casinha 'X' assume o valor de 'C'
}
else if(num==2) //se for 2
{
scanf("%d", &C); //lê o 'C'
printf("%d\n", marc[C]); //imprime a resposta para essa cor/número
}
}
return 0; //retorna a 0
}