Cod sursa(job #1800228)

Utilizator antanaAntonia Boca antana Data 7 noiembrie 2016 16:22:17
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.7 kb
#include <cstdio>
#define MAXN 100000
#define LOG 20

int k, n, r, lista[MAXN+1], nxt[MAXN+1], val[MAXN+1], eu[2*MAXN+1], h[2*MAXN+1], pos[MAXN+1], lg[2*MAXN+1];
int rmq[LOG][MAXN*4];

inline int mini(int a, int b){
    return (a < b ? a : b);
}

inline int maxi(int a, int b){
    return (a > b ? a : b);
}

inline void adauga(int x, int y)
{
    val[++r] = y;
    nxt[r] = lista[x];
    lista[x] = r;
}

void dfs(int nod, int a)
{
    int p;

    eu[++k] = nod;
    pos[nod] = k;
    h[k] = a;

    p = lista[nod];

    while(p)
    {
        dfs(val[p], a+1);

        eu[++k] = nod;
        h[k] = a;

        p = nxt[p];
    }
}

void calc()
{
    int i, log;

    for(i=1; i<=k; ++i)
        rmq[0][i] = i;

    for(log = 1; (1<<log)<=k; ++log)
        for(i=1; i+(1<<log)-1<=k; ++i)
            if(h[rmq[log-1][i]] < h[rmq[log-1][i+(1<<(log-1))]])
                rmq[log][i] = rmq[log-1][i];
            else rmq[log][i] = rmq[log-1][i+(1<<(log-1))];
}

int query(int a, int b)
{
    int l;
    if(a == b)
        return a;

    l = lg[b-a+1];

    if(h[rmq[l][a]] < h[rmq[l][b-(1<<l)+1]])
        return rmq[l][a];
    return rmq[l][b-(1<<l)+1];
}

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

    int i, x, y, q;

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

    lg[2] = 1;
    for(i=3; i<=2*n; ++i)
        lg[i] = lg[i/2]+1;

    for(i=2; i<=n; ++i)
    {
        scanf("%d", &x);
        adauga(x, i);
    }

    dfs(1, 0);
    calc();

    for(i=1; i<=q; ++i)
    {
        scanf("%d%d", &x, &y);
        printf("%d\n", eu[query(mini(pos[x], pos[y]), maxi(pos[x], pos[y]))]);
    }

    return 0;
}