Cod sursa(job #2674059)

Utilizator redstonegamer22Andrei Ion redstonegamer22 Data 18 noiembrie 2020 15:37:42
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.16 kb
#include <bits/stdc++.h>

using namespace std;

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

const int NMAX = 100007;
const int LMAX = 18;

vector<int> sons[NMAX];
int euler[4 * NMAX];
int dpth[4 * NMAX];
int lg2[4 * NMAX];

int location[4 * NMAX];

int rmq[LMAX][(1<<LMAX) + 7];

int euler_size = 0;

void init_lg2()
{
    lg2[1] = 0;
    for(int i = 2; i < 4 * NMAX; i++)
        lg2[i] = 1 + lg2[i>>1];
}

void init_depth()
{
    for(int i = 0; i < 4*NMAX; i++)
        dpth[i] = 1e9;
}

void dfs(int node = 1, int depth = 0)
{
    euler[euler_size] = node;
    location[node] = euler_size;
    dpth[euler_size] = depth;

    euler_size++;

    for(auto son : sons[node])
    {
        dfs(son, depth + 1);
        euler[euler_size] = node;
        dpth[euler_size] = depth;

        euler_size++;
    }
}

void make_rmq()
{
    for(int i = 0; i < euler_size; i++)
        rmq[0][i] = i;

    for(int level = 1; level < LMAX; level++)
    {
        for(int i = 0; i < (1<<LMAX) - (1<<level); i++)
        {
            rmq[level][i] = rmq[level-1][i];
            if(dpth[rmq[level-1][i + (1<<level)/2]] < dpth[rmq[level][i]])
                rmq[level][i] = rmq[level-1][i + (1<<level)/2];
        }
    }
}

int get_rmq(int a, int b)
{
    a = location[a];
    b = location[b];

    if(a > b) swap(a, b);
    if(a == b) return rmq[0][a];

    int dif = b - a;
    int level = lg2[dif];

    int ans = rmq[level][a];
    if(dpth[rmq[level][b - (1<<level)]] < dpth[ans])
        ans = rmq[level][b - (1<<level)];

    return ans;
}

int main()
{
    int n; in >> n;
    int q; in >> q;

    for(int i = 2; i <= n; i++)
    {
        int rd; in >> rd;
        sons[rd].push_back(i);
    }

    init_depth();
    init_lg2();
    dfs();
    make_rmq();

    /*for(int i = 0; i < euler_size; i++)
        cout << euler[i] << " ";
    cout << endl;
    for(int i = 0; i < euler_size; i++)
        cout << dpth[i] << " ";*/

    //cout << rmq[1][2];

    for(int i = 0; i < q; i++)
    {
        int a, b; in >> a >> b;
        int ans = get_rmq(a, b);

        out << euler[ans] << "\n";
    }
}