Cod sursa(job #2818349)

Utilizator zsraduZamfir Radu zsradu Data 15 decembrie 2021 21:32:44
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.67 kb
#include <bits/stdc++.h>
#define MAXN 1000003
#define MAXQ 1000003

using namespace std;
ifstream f("test.in");
ofstream g("test.out");

vector<int> v[MAXN]; // contine fiii fiecarui nod
vector<int> euler;   // contine sirul reprezentarii Euler a arborelui
vector<int> h;       // contine inaltimile pt fiecare nod din reprezentarea Euler
int first[MAXN];     // contine prima pozitie din reprezentarea Euler pentru fiecare nod.
int arb[MAXN << 4];  // arborele de intervale pe care vom face query-uri

int n, nrq;    // numarul de noduri si numarul de query-uri
int sol, solh; // nodul solutie si inaltimea sa
int k;         // dimensiunea vectorilor din repr Euler
int st, dr;

void read()
{
    f >> n >> nrq;
    for (int i = 2; i <= n; i++)
    {
        int parent;
        f >> parent;
        v[parent].push_back(i);
    }
}

void make_euler(int nod, int height)
{
    euler.push_back(nod);
    h.push_back(height);
    first[nod] = euler.size() - 1;
    for (long unsigned int i = 0; i < v[nod].size(); i++)
    {
        make_euler(v[nod][i], height + 1);
        euler.push_back(nod);
        h.push_back(height);
    }
}

void build(int nod, int first, int last)
{
    if (first == last)
    {
        arb[nod] = first;
        return;
    }
    int mij = (first + last) / 2;
    int nodst = 2 * nod, noddr = 2 * nod + 1;
    build(nodst, first, mij);
    build(noddr, mij + 1, last);

    if (h[arb[nodst]] <= h[arb[noddr]])
        arb[nod] = arb[nodst];
    else
        arb[nod] = arb[noddr];
}

void query(int nod, int first, int last)
{
    if (st <= first && dr >= last)
    {
        if (h[arb[nod]] < solh)
        {
            sol = euler[arb[nod]];
            solh = h[arb[nod]];
        }
        return;
    }
    int mij = (first + last) / 2;
    if (st <= mij)
        query(2 * nod, first, mij);
    if (mij < dr)
        query(2 * nod + 1, mij + 1, last);
}

int LCA(int x, int y)
{
    st = first[x];
    dr = first[y];
    if (st > dr)
        swap(st, dr);

    sol = INT_MAX;
    solh = INT_MAX;
    query(1, 0, k - 1);
    return sol;
}

int main()
{
    //auto start = chrono::high_resolution_clock::now();

    read();
    make_euler(1, 0);
    k = euler.size();
    build(1, 0, k - 1);

    for (int i = 0; i < nrq; i++)
    {
        int nod1, nod2;
        f >> nod1 >> nod2;
        g << LCA(nod1, nod2) << '\n';
    }

    /*auto stop = chrono::high_resolution_clock::now();
    auto duration = chrono::duration_cast<chrono::milliseconds>(stop - start);
    cout << "\nTimp de rulare: " << duration.count() << " milisecunde\n";*/

    f.close();
    g.close();
    return 0;
}