Cod sursa(job #2049405)

Utilizator Coroian_DavidCoroian David Coroian_David Data 27 octombrie 2017 09:45:31
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.36 kb
#include <bits/stdc++.h>

#define MAX_N 100000
#define MAX_LOG 17

using namespace std;

FILE *f, *g;

int k;
int n, q;

int first[MAX_N + 1];

int nodul[MAX_N * 2 + 1];

int rmq[MAX_N * 2 + 1][MAX_LOG + 1];
int poz[MAX_N * 2 + 1][MAX_LOG + 1];

int edg;
int lst[MAX_N + 1];
int urm[MAX_N + 1];
int nod[MAX_N + 1];

void add(int a, int b)
{
    edg ++;

    nod[edg] = b;
    urm[edg] = lst[a];

    lst[a] = edg;
}

void readFile()
{
    f = fopen("lca.in", "r");

    fscanf(f, "%d%d", &n, &q);

    int i;
    int nr;
    for(i = 2; i <= n; i ++)
    {
        fscanf(f, "%d", &nr);

        add(nr, i);
    }
}

int depth;

void dfs(int a)
{
    depth ++;

    if(first[a] == 0)
        first[a] = k + 1;

    ++ k;
    rmq[k][0] = depth;
    poz[k][0] = k;
    nodul[k] = a;

    int p, u;
    for(p = lst[a]; p != 0; p = urm[p])
    {
        dfs(nod[p]);

        ++ k;
        rmq[k][0] = depth;
        poz[k][0] = k;
        nodul[k] = a;
    }

    depth --;
}

void RMQ()
{
    int i, j;
    int p, p2;

    for(j = 1; j <= MAX_LOG; j ++)
    {
        int p = (1 << (j - 1));
        int p2 = (1 << j);

        for(i = 1; i + p2 - 1 <= k; i ++)
        {
            if(rmq[i][j - 1] < rmq[i + p][j - 1])
            {
                rmq[i][j] = rmq[i][j - 1];
                poz[i][j] = poz[i][j - 1];
            }

            else
            {
                rmq[i][j] = rmq[i + p][j - 1];
                poz[i][j] = poz[i + p][j - 1];
            }
        }
    }
}

int lg[MAX_N * 2 + 1];

void getLg()
{
    lg[1] = 0;
    int i;
    for(i = 2; i <= k; i ++)
        lg[i] = lg[i >> 1] + 1;
}

void preCalc()
{
    dfs(1);

    getLg();

    RMQ();
}

int getMin(int st, int dr)
{
    if(st > dr)
        swap(st, dr);

    int len = dr - st + 1;
    int p2 = lg[len];
    int diff = len - (1 << p2);

    return min(rmq[st][p2], rmq[st + diff][p2]) == rmq[st][p2] ? nodul[poz[st][p2]] : nodul[poz[st + diff][p2]];
}

void ansQues()
{
    g = fopen("lca.out", "w");

    int a, b;
    while(q > 0)
    {
        fscanf(f, "%d%d", &a, &b);

        fprintf(g, "%d\n", getMin(first[a], first[b]));

        q --;
    }

    fclose(f);
    fclose(g);
}

int main()
{
    readFile();

    preCalc();

    ansQues();

    return 0;
}