Solução por Samyra Almeida
Conhecimentos prévios necessários:
Dividiremos o vetor em blocos de tamanho . Com isso chamaremos de é o igual a quantidade de pulos do buraco até a primeira posição fora do bloco de , é a ultima posição, do mesmo bloco de , que a bola pula se fosse jogada na posição , é a próxima posição que a bola pula se for jogada na posição e o vetor v[] guarda o poder de cada buraco.
Antes de lermos os queries, iremos montar os vetores. Para o -ésimo buraco iremos fazer:
Vamos percorrer todos os buracos que estão entre e o inicio de seu bloco, a partir dai iremos anualizar três possíveis casos:
Para evitar possíveis duvidas, poder do buraco e é o buraco que eu estou, logo a posição que eu irei após cair no -ésimo buraco. Com isso, vamos analisar os casos =D!
- Caso : Nesse caso a bola irá sair do vetor. Portanto:
- Caso , sendo : Nesse caso a bola irá sair do vetor. Portanto:
- , a quantidade de pulos que v[j] + j leva até o final do bloco mais , ou seja, meu pulo até .
- , ultima posição que pula dentro do bloco é a mesma de
- , a próxima posição é
- Caso está entre e : Nesse caso o próximo pulo será para fora do bloco de , então faremos:
Bem, após tudo isso, iremos ler e processar as queries:
Para as queries do tipo , perceba que só precisamos atualizar o bloco em pertence pois como nós só calculamos a quantidade de pulos necessários para sair de um buraco até o final de seu bloco a alteração na potencia do -ésimo buraco só interfere no seu próprio bloco. Para isso, iremos fazer as mesmas operações que fizemos para construir os vetores, , e , porem, somente para os buracos de até o inicio de seu bloco.
E para as queries do tipo iremos criar duas variáveis, , que no inicio é, e , que no inicio é , e faremos um onde para cada iteração faremos:
- , somamos a quantidade de pulos ate sair do bloco que está.
- , atualizamos a ultima posição.
- Checamos se , ou seja, se o próximo pulo sai do vetor, se sim, paramos o loop, se não, fazemos pulamos para a próxima posição.
Ao final do loop, basta imprimir e .
Segue o código solução para maior compressão:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NOIC - Problemas da Semana 69 - Intermediário | |
// Solução por Samyra Almeida | |
#include <bits/stdc++.h> | |
using namespace std; | |
const int maxn = 1e5+10, root = 340; // declaro maxn e root como constantes, | |
// observe que coloquei o root como 340 pq por alguma razao fica um pouquinho mais rapido quando n e no maximo 10^5 | |
// nos testamos em alguns juizes e ficou mais rapido, mas se quiser usar como 320 fique a vontade. | |
int n, m; | |
int v[maxn], qtd[maxn], ultimo[maxn], prox[maxn]; // declaro as variaveis e vetores que irei precisar | |
void build() | |
{ | |
for(int i = n ; i > 0 ; --i) // passo por todas as posiçoes do vetor, ou seja, por todos os buracos | |
{ | |
int ini, fim; | |
ini = i/root; | |
fim = ini + 1; | |
ini *= root, fim *= root; // calculo a primeira e a ultima posicao do bloco que i pertence | |
// OBS: pode ficar um pouco confuso mas tente observar que na verdade a variavel fim guarda | |
// a primeira posicao do proximo bloco, ou seja, o bloco de i abrange as posiçoes de ini ate fim - 1. | |
for(int j = i ; j >= max(ini, 1) ; --j) // percorro da posiçao i ate o inicio do bloco de i | |
{ | |
if(v[j] + j > n) // se o proximo pulo sai do vetor | |
{ | |
qtd[j] = 1; // a quantidade de pulos para sair do vetor e 1 | |
ultimo[j] = j; // a ultima posiçao que eu pulei dentro do meu bloco foi a posiçao j | |
} | |
else if(v[j] + j < fim) // se o proximo pulo e dentro o meu bloco, seria a mesma coisa de testar v[j] + j <= fim - 1 | |
{ | |
qtd[j] = qtd[j + v[j]] + 1; // a quantidade de pulos ate o final do bloco e igual a quantidade de pulos que o meu proximo cara deu ate o final do bloco mais 1 (meu pulo ate v[j] + j) | |
ultimo[j] = ultimo[j + v[j]]; // o ultimo de j e o mesmo que o de v[j] + j | |
} | |
else // se o meu proximo pulo for em alguma outra posiçao, ainda dentro do vetor mas fora do meu bloco | |
{ | |
qtd[j] = 1; // a quantidade de pulos para sair do vetor e 1 | |
ultimo[j] = j; // a ultima posiçao que eu pulei dentro do meu bloco foi a posiçao j | |
} | |
prox[j] = j + v[j]; // atualizo a posiçao do proximo pulo de j | |
} | |
} | |
} | |
int main() | |
{ | |
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); | |
cin >> n >> m; | |
for(int i = 1 ; i <= n ; ++i) cin >> v[i]; | |
build(); // monto os vetores qtd, ultimo e prox. | |
for(int i = 0 ; i < m ; ++i) // processo todas as queries | |
{ | |
int type, a; | |
cin >> type >> a; | |
if(type) // se for do tipo 1 | |
{ | |
int pulos = 0, x = a; // no inicio nao dei nenhum pulo e estou na posiçao a | |
while(true) // enquanto eu preciso pular de bloco | |
{ | |
pulos += qtd[x]; // somo a pulos a quantidade de pulos para sair da posicao x ate a ultima posiçao que eu vou pular em meu bloco | |
x = ultimo[x]; // pulo ate a ultima posiçao que eu consigo em meu bloco | |
if(prox[x] > n) break; // se o proximo pulo for sair do vetor, paro o loop | |
x = prox[x]; // caso contrario, pulo para a proxima posicao | |
} | |
cout << x << " " << pulos << "\n"; // imprimo a resposta | |
} | |
else // se a query for do tipo 0 | |
{ | |
int b; | |
cin >> b; | |
v[a] = b; // atualizo a potencia do buraco a | |
int ini, fim; | |
ini = a/root; | |
fim = ini + 1; | |
ini *= root, fim *= root; // calculo a primeira e a ultima posicao do bloco que a pertence | |
// OBS: pode ficar um pouco confuso mas tente observar que na verdade a variavel fim guarda | |
//a primeira posicao do proximo bloco, ou seja, o bloco de a abrange as posiçoes de ini ate fim - 1. | |
for(int j = a ; j >= max(ini, 1) ; --j) // percorro o bloco da posiçao a ate o inicio do bloco | |
{ | |
if(v[j] + j > n) // se o proximo pulo sai do vetor | |
{ | |
qtd[j] = 1; // a quantidade de pulos para sair do vetor e 1 | |
ultimo[j] = j; // a ultima posiçao que eu pulei dentro do meu bloco foi a posiçao j | |
} | |
else if(v[j] + j < fim) // se o proximo pulo e dentro o meu bloco, seria a mesma coisa de testar v[j] + j <= fim - 1 | |
{ | |
qtd[j] = qtd[j + v[j]] + 1; // a quantidade de pulos ate o final do bloco e igual a quantidade de pulos que o meu proximo cara deu ate o final do bloco mais 1 (meu pulo ate v[j] + j) | |
ultimo[j] = ultimo[j + v[j]]; // o ultimo de j e o mesmo que o de v[j] + j | |
} | |
else // se o meu proximo pulo for em alguma outra posiçao, ainda dentro do vetor mas fora do meu bloco | |
{ | |
qtd[j] = 1; // a quantidade de pulos para sair do vetor e 1 | |
ultimo[j] = j; // a ultima posiçao que eu pulei dentro do meu bloco foi a posiçao j | |
} | |
prox[j] = j + v[j]; // atualizo o proximo cara que eu irei pular. | |
} | |
} | |
} | |
} |