Cod sursa(job #2175139)

Utilizator razvan99hHorhat Razvan razvan99h Data 16 martie 2018 15:35:42
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.92 kb
#include <iostream>
#include <fstream>
#include <vector>
#define DM 100005
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, m, val, u, v, rmq[20][DM * 2], log[DM * 2], eul[DM * 2], dim, lvl[DM * 2], first[DM * 2];
vector <int> g[DM];

void dfs_euler(int nod, int level)
{
    dim++;
    eul[dim] = nod; // repr. euler a arb.
    lvl[dim] = level; // nivelul nodului in arb.
    first[nod] = dim; // prima aparitie a nodului in repr. euler a arb.
    for(auto it : g[nod])
    {
        dfs_euler(it, level + 1);
        dim++;
        eul[dim] = nod;
        lvl[dim] = level;
    }
}
void build_rmq() // rmq[k][i] = pozitia nodului de nivel minim din secventa din repr. eul. a arb. ce incepe pe poz i si are lungime 2^k
{
    log[0] = -1;
    for(int i = 1; i <= dim; i++)
    {
        log[i] = 1 + log[i / 2];
        rmq[0][i] = i;
    }
    for(int k = 1; k <= log[dim]; k++)
        for(int i = 1; i + (1 << k) - 1 <= dim; i++)
        {
            int l = (1 << (k - 1));
            if(lvl[ rmq[k - 1][i] ] < lvl[ rmq[k - 1][i + l] ])
                rmq[k][i] = rmq[k - 1][i];
            else  rmq[k][i] = rmq[k - 1][i + l];
        }
}
int lca(int u, int v) //Cel mai apropiat strămoş comun a 2 noduri este nodul de nivel minim dintre primele apariţii ale nodurilor din query din reprezentarea Euler a arborelui.
{
    u = first[u];
    v = first[v];
    if(u > v)
        swap(u, v);
    int l = log[v - u + 1];
    if(lvl[ rmq[l][u] ] < lvl[ rmq[l][v - (1 << l) + 1] ])
        return eul[ rmq[l][u] ];
    else return eul[ rmq[l][v - (1 << l) + 1] ];
}
int main()
{
    fin >> n >> m;
    for(int i = 1; i < n; i++)
    {
        fin >> val;
        g[val].push_back(i + 1); // arborele
    }

    dfs_euler(1, 0);

    build_rmq();

    for(int i = 1; i <= m; i++)
    {
        fin >> u >> v;
        fout << lca(u, v) << '\n';
    }
    return 0;
}