Cod sursa(job #2422478)

Utilizator alexoloieriAlexandru Oloieri alexoloieri Data 18 mai 2019 21:56:39
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.63 kb
#include <bits/stdc++.h>
#define nmax 100005
#define pb push_back
using namespace std;
int peuler[nmax*2], ap[nmax], h[nmax*2];
int rmq[nmax*2][50];
int n, inalt, m, x, act, y;
vector<int>g[nmax];
void dfs(int k)
{
    peuler[++act] = k;
    h[act] = inalt;
    ap[k] = act;
    for (auto x:g[k])
    {
        ++inalt;
        dfs(x);
        --inalt;
        peuler[++act] = k;
        h[act] = inalt;
    }
}
int l2(int x) // log2(x)
{
    if (x<=1) return 0;
    int ans = 0, p2 = 1;
    while(true)
    {
        if (p2>x) return ans-1;
        ++ans, p2*=2;
    }
}
void rmqq()
{
    for (int i=1;i<=act;++i)
        rmq[i][0] = i;
    for (int j=1;(1<<j) <= act; ++j)
        for (int i=1;i + (1<<j) -1 <=act;++i)
             if (h[rmq[i][j-1]] < h[rmq[i+(1<<(j-1))][j-1]])
                rmq[i][j] = rmq[i][j-1];
            else
                rmq[i][j] = rmq[i+(1<<(j-1))][j-1];
}
int lca(int x, int y)
{
    int ap1 = ap[x];
    int ap2 = ap[y];
    if (ap1 > ap2) swap(ap1, ap2);
    int dist = ap2 - ap1 + 1;
    int lg2 = l2(dist);
    int add = dist - (1<<lg2);
    if (h[rmq[ap1][lg2]] <= h[rmq[ap1+add][lg2]])
        return peuler[rmq[ap1][lg2]];
    else
        return peuler[rmq[ap1+add][lg2]];
}

int main()
{
    freopen("lca.in","r",stdin);
    freopen("lca.out","w",stdout);
    scanf("%d %d",&n,&m);
    for (int i=2;i<=n;++i)
    {
        scanf("%d",&x);
        g[x].pb(i);
    }
    dfs(1);
    rmqq();
    for (int i=1;i<=m;++i)
    {
        scanf("%d %d",&x,&y);
        printf("%d\n", lca(x, y));
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}