Cod sursa(job #1652892)

Utilizator Toast97Calin Farcas Toast97 Data 15 martie 2016 16:06:42
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.89 kb
#include <fstream>
#include <math.h>

using namespace std;

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

struct nod
{
    int info;
    nod *adr;
} *v[100005];

void adauga (int x, int y)
{
    nod *c;
    c = new nod;
    c -> info = y;
    c -> adr = v[x];
    v[x] = c;
}

int euler[200005], h[200005], first[100005], n, m, e = 0, lowest[100005][18];

void citire ()
{
    f >> n >> m;

    int nr;

    for (int i = 1; i <= n - 1; i ++)
    {
        f >> nr;
        adauga (i + 1, nr);
        adauga (nr, i + 1);
    }
}

void dfs (int tata, int node, int depth)
{
    h[++ e] = depth;
    euler[e] = node;

    if (! first[node])
        first[node] = e;

    nod *c = v[node];

    while (c)
    {
        if (c -> info != tata)
        {
            dfs (node, c -> info, depth + 1);
            h[++ e] = depth;
            euler[e] = node;
        }

        c = c -> adr;
    }
}

void rmq_precalc ()
{
    for (int i = 1; i <= e; i ++)
        lowest[i][0] = i;

    for (int j = 1; (1 << j) <= e; j ++)
        for (int i = 1; i + (1 << j) - 1 <= e; i ++)
            if(h[lowest[i][j - 1]] < h[lowest[i + (1 << (j - 1))][j - 1]])
                lowest[i][j] = lowest[i][j - 1];
            else
                lowest[i][j] = lowest[i + (1 << (j - 1))][j - 1];
}

int lca (int x, int y)
{
    int minim = min (first[x], first[y]), maxim = max (first[x], first[y]);

    x = minim;
    y = maxim;

    int k = log2 (y - x + 1);

    if (h[lowest[x][k]] < h[lowest[y - (1 << k) + 1][k]])
        return euler[lowest[x][k]];
    return euler[lowest[y - (1 << k) + 1][k]];
}

int main()
{
    citire ();

    dfs (0, 1, 0);
    rmq_precalc ();

    int x, y;

    for (int i = 1; i <= m; i ++)
    {
        f >> x >> y;
        g << lca(x, y) << '\n';
    }

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