Cod sursa(job #2874148)

Utilizator 123utilizator321Stanescu Liviu 123utilizator321 Data 19 martie 2022 13:01:40
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.69 kb
#include <bits/stdc++.h>
using namespace std;

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

const int NMAX = 1e5+5, LMAX = 18;
vector<int> euler, g[NMAX];
int invers[NMAX], depth[NMAX];

void liniarizare(int node, int father, int cnt_depth)
{
    depth[node] = cnt_depth;
    euler.push_back(node);
    for(auto son: g[node])
    {
        if(son == father)
            continue;
        liniarizare(son, node, cnt_depth + 1);
        euler.push_back(node);
    }
}

int rmq[LMAX][1 << LMAX];
void init_rmq()
{
    depth[0] = NMAX;
    for(int i = 0; i < euler.size(); i++)
    {
        rmq[0][i] = euler[i];
        invers[euler[i]] = i;
    }
    
    for(int level = 1; level < LMAX; level++)
        for(int i = 0; i + (1 << level) / 2 < euler.size(); i++)
        {
            int a = rmq[level - 1][i];
            int b = rmq[level - 1][i + (1 << level) / 2];
            if(depth[a] > depth[b])
                rmq[level][i] = b;
            else
                rmq[level][i] = a;
        }
}

int query_rmq(int a, int b)
{
    int posa = invers[a];
    int posb = invers[b];
    if(posa > posb)
        swap(posa, posb);
    if(posa == posb)
        return rmq[0][posa];
    
    int length = posb - posa + 1;
    int lg = 31 - __builtin_clz(length);
    
    a = rmq[lg][posa];
    b = rmq[lg][posb - (1 << lg) + 1];
    
    if(depth[a] > depth[b]) 
        return b;
    return a;
}

int main()
{
    int n, m;
    fin >> n >> m;
    for(int i = 2; i <= n; i++)
    {
        int x;
        fin >> x;
        g[x].push_back(i);
    }
    
    liniarizare(1, -1, 1);
    init_rmq();
    
    while(m--)
    {
        int a, b;
        fin >> a >> b;
        fout << query_rmq(a, b) << '\n';
    }
    return 0;
}