Cod sursa(job #2759462)

Utilizator NeacsuMihaiNeacsu Mihai NeacsuMihai Data 17 iunie 2021 22:57:35
Problema Stramosi Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.16 kb
/*
    Observ ca numarul P poate fi descompus in baza 2
    si exact asta fac
    pt fiecare persoana tin minte stramosii pe puteri ale lui 2
    si cand vreau sa fac al P-lea stramos, parcurg in descompunerea lui 2
    si gasesc in timp logaritmic

    timp: O(log N) pe query
    memorie: O(N log N)
*/

/*
    Problema imi da foarte comod '0' daca nu are stramos
    adica o sa tin 0 radacina
*/

#include <iostream>
#include <fstream>
#include <vector>

#define NMAX 250000 //doua sute cincizeci de mii
#define LOGMAX 17

using namespace std;

ifstream fin ("stramosi.in");
ofstream fout ("stramosi.out");

vector<int> v[NMAX + 1];
int tt[NMAX + 1][LOGMAX + 1];

void DFS(int nod, int height){
    for(int i = 0; i < v[nod].size(); i++){
        int X = v[nod][i];

        //ii calculez stramosii lui X, dupa care il dau mai departe

        //pornesc cu j de la 1 pt ca tt[X][0] il stiu deja din citire
        for(int j = 1; (1 << j) <= height; j++){ //un for foarte gandit
            //practic iau doar tatii care exista
            tt[X][j] = tt[ tt[X][j - 1] ][j - 1];
        }

        DFS(X, height + 1);
    }
}

inline int logS(int x){
    /*
        Aceasta functie primeste ca parametru un element care este sigur de forma 2^K
        deci are un singur bit egal cu 1
        pe care il caut printr-o parcurgere
        si returnez pozitia pe care l-am gasit
        facand astfel un log in baza 2
    */

    for(int j = 0; (1 << j) <= x; j++){
        if(x & (1 << j) ){
            return j;
        }
    }
}

inline int query(int Q, int P){
    int nod = Q;
    for(int i = P; i >= 1; i -= i & (-i)){
        //o analogie cu AIB
        nod = tt[nod][ logS( i & (-i) ) ];
    }

    return nod;
}

int main()
{
    int N, M;
    fin >> N >> M;

    for(int i = 1; i <= N; i++){
        fin >> tt[i][0];

        v[ tt[i][0] ].push_back(i);
    }

    DFS(0, 0); //de fapt asta e un fel de buildTT[][]
    //adica aici pregatesc pt query-urile ce urmeaza

    for(int i = 1; i <= M; i++){
        int Q, P;
        fin >> Q >> P;

        fout << query(Q, P) << "\n";
    }

    return 0;
}