Cod sursa(job #1537870)

Utilizator MarcusPopMarcus Pop MarcusPop Data 28 noiembrie 2015 11:24:05
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.97 kb
#include <iostream>
#include <fstream>
#include <vector>

///  RMQ, DFS, parcurgere Euler

using namespace std;

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

vector <int> v[100005]; /// vectorul de tati

int     n, m;
int     level[200005], euler[2000005], first[100005], log[100005];
int     cnt;
int     rmq[18][200005]; /// minimul
int     nod[18][200005]; /// nodul

void    dfs(int x)
{
    /// cnt - contor
    euler[++cnt] = x;
    first[x] = cnt;
    for (auto fiu:v[x])
    {
        level[fiu] = level[x] + 1;
        dfs(fiu);
        euler[++cnt] = x;
    }
}

void    make_log(void)
{
    log[1] = 0;
    for (int i = 2; i <= cnt; i++)
        log[i] = log[i / 2] + 1;
}

int     lca(int x, int y)
{
    int     p;
    int     diff;

    x = first[x];
    y = first[y];
    if (x > y)
        swap(x, y);
    diff = y  - x + 1;
    p = log[diff];
    if (rmq[p][x] < rmq[p][y - (1 << p) + 1])
        return nod[p][x];
    return  nod[p][y - (1 << p) + 1];
}

void    rezolvare()
{
    int     x;
    int     nod1, nod2;

    f >> n >> m;
    for (int i = 1; i <= n - 1; i++)
    {
        f >> x;
        v[x].push_back(i + 1);
    }
    dfs(1);
    make_log();
    for (int i = 1; i <= cnt; i++)
    {
        rmq[0][i] = level[euler[i]];
        nod[0][i] = euler[i];
    }
    for (int i = 1; (1 << i) <= cnt; i++)
    {
        for (int j = 1; j + (1 << (i - 1)) <= cnt; j++)
        {
            if (rmq[i - 1][j] < rmq[i - 1][j + (1 << (i - 1))])
            {
                rmq[i][j] = rmq[i - 1][j];
                nod[i][j] = nod[i - 1][j];
            }
            else
            {
                rmq[i][j] = rmq[i - 1][j + (1 << (i - 1))];
                nod[i][j] = nod[i - 1][j + (1 << (i - 1))];
            }
        }
    }
    for (int i = 1; i <= m; i++)
    {
        f >> nod1 >> nod2;
        g << lca(nod1, nod2) << '\n';
    }
}
int main()
{
    rezolvare();
    return 0;
}