Pagini recente » Cod sursa (job #1636640) | Cod sursa (job #2344746) | Cod sursa (job #2273298) | Cod sursa (job #1880779) | Cod sursa (job #3207617)
#include <bits/stdc++.h>
using namespace std;
#ifndef LOCAL
ifstream in("stramosi.in");
ofstream out("stramosi.out");
#define cin in
#define cout out
#endif // LOCAL
const int nmax = 25e4 + 7;
const int exp_max = 20;
int parinte[nmax];
// functia saritura_p2 in conceptele programarii functionale (nu prea se aplica la olimpiada)
// este o functie PURA -> memoizabila
// 1. nu are efecte secundare (nu schimba variabile globale)
// 2. daca primeste acelasi input, mereu ofera inapoi acelasi output
// Observatia Importanta! Este o functie recursiva care se apeleaza pe sine
// --> Daca o memoizam, va merge in O(1) amortizat!
int memo[nmax][exp_max];
int saritura_p2(int node, int exp) {
// face o saritura de marime 2^exp in sus, pornind de la nodul nod
const int speed = 3;
// Implementarea 1. Naiv
if(speed == 1) {
for(int rep = 0; rep < (1 << exp); rep++) {
node = parinte[node];
}
return node;
}
if(speed == 2) {
if(exp == 0) {
// saritura de marime 2^0 = 1 inseamna doar parinte[node]
return parinte[node];
}
// altfel, eu pot sa fac o saritura de marime 2^exp, din 2 sarituri mai mici
// fiecare de marimea 2 ^ (exp - 1)
node = saritura_p2(node, exp - 1);
node = saritura_p2(node, exp - 1);
return node;
}
if(speed == 3) {
if(exp == 0) {
return parinte[node];
}
if(memo[node][exp] != -1) { // valoarea initiala = -1
return memo[node][exp];
}
int init_node = node;
node = saritura_p2(node, exp - 1);
node = saritura_p2(node, exp - 1);
memo[init_node][exp] = node;
return node;
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
for(int i = 0; i < nmax; i++) {
for(int j = 0; j < exp_max; j++) {
memo[i][j] = -1;
}
}
int n, q; cin >> n >> q;
for(int i = 1; i <= n; i++) {
cin >> parinte[i];
}
// bottom-up DP
for(int exp = 0; exp < exp_max; exp++) {
for(int node = 0; node < nmax; node++) {
if(exp == 0) memo[node][exp] = parinte[exp];
else {
memo[node][exp] = memo[memo[node][exp - 1]][exp - 1];
}
}
}
while(q--) {
int node, pas;
cin >> node >> pas;
// Cum spargem pas in puteri de 2?
const int exp_max = 18;
for(int exp = 0; exp <= exp_max; exp++) {
// verific daca bitul de 1 care corespunde lui 2^exp este setat in pas
if(pas & (1 << exp)) {
node = saritura_p2(node, exp);
}
}
cout << node << '\n';
}
}