Cod sursa(job #1839415)

Utilizator vladm98Munteanu Vlad vladm98 Data 2 ianuarie 2017 21:18:38
Problema Lowest Common Ancestor Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 3.77 kb
#include <bits/stdc++.h>
#define fit(v, r) for(vector<int>::iterator v=r.begin();v!=r.end();++v)
using namespace std;
const int MAX = 100001;
map <int, int> normalizare;
int n, subarb[MAX], numar_lanturi, rad;int invers_normalizat[MAX], gr[MAX], lant[MAX], gr_lant[MAX], tata[25][MAX], n_l[MAX], n_n[MAX], tata_nd[MAX];vector <int> graf[MAX];int randi[MAX];int b_l[MAX];vector <int> g_l[MAX];

void dfs (int nod, int boss, int nivel)
{
    subarb[nod] = 1;
    n_n[nod] = nivel;
    tata_nd[nod] = boss;
    int maxim = 0;
    fit(x, graf[nod])
    {
        if (*x != boss)
        {
            dfs(*x, nod, nivel+1);
            subarb[nod] += subarb[*x];
            if (subarb[*x] > maxim)
            {
                maxim = subarb[*x];
                lant[nod] = lant[*x];
            }
        }
    }
    if (maxim)
    {
        b_l[lant[nod]] = nod;
        fit(x, graf[nod])
            if (*x != boss)
                if (lant[*x] != lant[nod])
                    tata[0][lant[*x]] = lant[nod], g_l[lant[nod]].push_back(lant[*x]), b_l[lant[*x]]=nod;
        return ;
    }
    ++numar_lanturi;
    lant[nod] = numar_lanturi;
    b_l[lant[nod]] = nod;
}
void dfs_nivele (int lant, int nivel)
{
    n_l[lant] = nivel;
    fit(x, g_l[lant])
        dfs_nivele(*x, nivel+1);
}
int LCA (int x, int y)
{
    int lx = lant[x], ly = lant[y];
    int copiex = lx, copiey = ly;
    if (lx == ly)
    {
        if (n_n[x] > n_n[y])
            return y;
        return x;
    }
    int nlx = n_l[lx];int nly = n_l[ly];int DN = nlx-nly, p = 1, put=0;
    if (DN < 0) DN = -DN;
    while (p<<1 <= DN)
        p<<=1, ++put;
    if (nlx < nly) swap(x,y);
    lx = lant[x],ly = lant[y],copiex = lx, copiey = ly, nlx = n_l[lx], nly = n_l[ly];
    for (int i = put; i>=0; --i)
        if (1<<i <= DN)
            lx = tata[i][lx],DN = DN - (1<<i);
    if (lx == ly)
    {
        lx = copiex;DN = nlx-nly;--DN;p = 1;put = 0;
        while (p<<1 <= DN)
            p<<=1,++put;
        for (int i = put; i>=0; --i)
            if (1<<i <= DN)
                lx = tata[i][lx],DN = DN - (1<<i);
        x = b_l[lx];
        if (n_n[x] > n_n[y])
            return y;
        return x;
    }
    nlx = n_l[lx];
    put = 0;
    p = 1;
    while (p<<1 < nlx)
        p<<=1, ++put;
    for (int i = put; i>=0; --i)
        if (1<<i < nlx && tata[i][lx] != tata[i][ly])
            lx = tata[i][lx],ly = tata[i][ly],nlx = nlx - (1<<i);
    x = b_l[lx];y = b_l[ly];
    if (n_n[x] > n_n[y])
        return y;
    return x;
}

int readInt()
{
    int raspuns = 0;char c; bool minus = 0;
    while (true)
    {
        c = cin.get();
        if ((c >= '0' && c<='9') || c == '-')
        {
            if (c == '-')
                minus = 1;
            else raspuns = c-'0';
            break;
        }
    }
    while (true)
    {
        c = cin.get();
        if (c<'0' || c>'9')
            break;
        raspuns = raspuns * 10 + c-'0';
    }
    if (minus)
        return -raspuns;
    return raspuns;
}
int main()
{
    freopen ("lca.in", "r", stdin);
    freopen ("lca.out", "w", stdout);
    int m, x, y;
    n = readInt();
    m = readInt();
    for (int i = 2; i<= n; ++i)
    {
        x = readInt();
        graf[x].push_back(i);
    }

    dfs(1, 0, 1);
    dfs_nivele(lant[1], 1);
    for (int i = 1; i<25; ++i)
    {
        bool verif = 0;
        for (int j = 1; j<= numar_lanturi; ++j)
        {
            tata[i][j] = tata[i-1][tata[i-1][j]];
            if (tata[i][j]) verif = 1;
        }
        if (verif == 0)
            break;
    }
    for (int i = 0; i<m; ++i)
    {
    int x, y, k, lca, tatalca;
    x = readInt(), y = readInt();
    cout << LCA(x, y) << '\n';
    }
    return 0;
}