Cod sursa(job #1452424)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 20 iunie 2015 20:17:37
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.69 kb
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int Nmax = 100010;
const int LgMax = 19;

int n , m , i , dad , node1 , node2;
int ap[Nmax] , Log[Nmax<<1];
pair < int , int > D[LgMax][Nmax<<1];

vector < int > g[Nmax];
vector < pair < int , int > > euler;

void dfs(int node , int level)
{
    euler.push_back({node , level});
    for (int i = 0; i < g[node].size(); ++i)
    {
        dfs(g[node][i] , level + 1);
        euler.push_back({node , level});
    }
}

void rmq()
{
    int i , j , n = euler.size();
    for (i = 1; i <= n; ++i)
    {
        D[0][i] = euler[i-1];
        if (!ap[euler[i-1].first])
            ap[euler[i-1].first] = i;
    }

    for (Log[1] = 0, i = 2; i <= n; ++i)
        Log[i] = Log[i>>1] + 1;
    for (i = 1; i <= Log[n]; ++i)
        for (j = 1; j <= n - (1 << i) + 1; ++j)
        {
            if (D[i-1][j].second < D[i-1][j+(1<<(i-1))].second)
                D[i][j] = D[i-1][j];
            else D[i][j] = D[i-1][j+(1<<(i-1))];
        }
}

int main()
{
    freopen("lca.in","r",stdin);
    freopen("lca.out","w",stdout);

    scanf("%d %d", &n, &m);

    for (i = 2; i <= n; ++i)
    {
        scanf("%d", &dad);
        g[dad].push_back(i);
    }

    dfs(1 , 0); rmq();

    for (i = 1; i <= m; ++i)
    {
        scanf("%d %d", &node1, &node2);
        int left = ap[node1]; int right = ap[node2]; if (left > right) swap(left , right);
        int ind = Log[right-left+1];
        if (D[ind][left].second < D[ind][right-(1<<ind)+1].second)
            printf("%d\n", D[ind][left].first);
        else printf("%d\n", D[ind][right-(1<<ind)+1].first);
    }

    return 0;
}