Cod sursa(job #1525922)

Utilizator bogdanciurezubogdan ciurezu bogdanciurezu Data 15 noiembrie 2015 18:32:42
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.89 kb
#include <fstream>
#include <vector>

using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");

const int nmax = 100050;
int n, m;

vector < int > Graf[nmax], euler, niv, logaritm, prmAp;

int rmq[20][2 * nmax];

void parcEuler(int poz){
    euler.push_back(poz);
    prmAp[poz] = euler.size();

    for(int i = 0; i < Graf[poz].size(); ++i){
        if( !prmAp[ Graf[poz][i] ] ){
            niv[ Graf[poz][i] ] = niv[poz] + 1;

            parcEuler( Graf[poz][i]);
            euler.push_back(poz);
        }
    }
}

void rangeMinQuerry(){
    int s;

    for(int i = 1; (1 << i) <= euler.size(); ++i){
        for(int j = 1; j <= euler.size() - (1 << i) + 1; ++j){
            s = 1 << (i - 1);

            rmq[i][j] = niv[ rmq[i - 1][j] ] < niv[ rmq[i - 1][j + s] ] ? rmq[i - 1][j] : rmq[i - 1][j + s];
        }
    }
}

int main()
{
    f>>n>>m;
    niv.resize(n + 1, 0);
    prmAp.resize(n + 1, 0);

    for(int i = 2, x; i <= n; ++i){
        f>>x;

        Graf[x].push_back(i);
    }

   parcEuler(1);

    for(int i = 0; i < euler.size(); ++i){
        rmq[0][i + 1] = euler[i];
    }
    rangeMinQuerry();

    logaritm.push_back(-1);
    for(int i = 1; i <= euler.size(); ++i) logaritm.push_back( logaritm[ (i >> 1) ] + 1 );

   /*
     for(int i = 0; (1 << i) <= euler.size(); ++i){
        for(int j = 1; j <= euler.size() - (1 << i) + 1; ++j){
            g<<rmq[i][j]<<' ';
        }
        g<<'\n';
    }*/

    int diff, trm1, trm2, sol, lg;

    for(int i = 1, x, y; i <= m; ++i){
        f>>x>>y;

        if(prmAp[y] < prmAp[x]){
            swap(x, y);
        }

        lg = logaritm[prmAp[y] - prmAp[x] + 1];

        trm1 = rmq[ lg ][prmAp[x]];
        trm2 = rmq[ lg ][ prmAp[y] - ( 1 << lg ) + 1 ];


        sol = niv[trm1] < niv[trm2] ? trm1 : trm2;

       g<<sol<<'\n';
    }
    return 0;
}