Cod sursa(job #2989518)

Utilizator stefan05Vasilache Stefan stefan05 Data 6 martie 2023 18:38:41
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.64 kb
#include <fstream>
#include <vector>

#define NMAX 100005

using namespace std;

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

int n, m;
int x, y;
vector<int> l[NMAX];
vector<pair<int, int>> euler; int first[NMAX];
bool f[NMAX];
int rmq[NMAX*2][20];
int logaritm[2*NMAX];
int i, j;

void dfs(int, int);
void calcrmq();
int lca(int, int);

int main()
{
    for (i = 2; i < 2*NMAX; ++i)
        logaritm[i] = logaritm[i/2] + 1;

    fin >>n>>m;
    for (i = 2; i <= n; ++i)
    {
        fin >>x;
        l[i].push_back(x);
        l[x].push_back(i);
    }

    dfs(1, 0);
    calcrmq();

    for (i = 1; i <= m; ++i)
    {
        fin >>x>>y;
        fout <<lca(x, y)<<'\n';
    }
    fout.close();
    return 0;
}

int lca(int x, int y)
{
    x = first[x]; y = first[y];

    if (x > y) swap(x, y);

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

    int l = rmq[x][lg];
    int r = rmq[y-(1<<lg)+1][lg];

    return (euler[l].second < euler[r].second)? euler[l].first: euler[r].first;
}

void calcrmq()
{
    int n = euler.size();
    int l, r;
    int i, j;

    for (i = 0; i < n; ++i)
        rmq[i][0] = i;

    for (j = 1; (1<<j) <= n; ++j)
        for (i = 0; i+(1<<j)-1 < n; ++i)
        {
            l = rmq[i][j-1];
            r = rmq[i+(1<<(j-1))][j-1];

            rmq[i][j] = (euler[l].second < euler[r].second)? l: r;
        }
}

void dfs(int vf, int lvl)
{
    f[vf] = 1;
    first[vf] = euler.size();
    euler.push_back({vf, lvl});

    for (auto vfnou: l[vf])
        if (!f[vfnou])
        {
            dfs(vfnou, lvl+1);
            euler.push_back({vf, lvl});
        }
}