Cod sursa(job #2198234)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 23 aprilie 2018 22:39:27
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.72 kb
#include <bits/stdc++.h>
#define dimn 100005
#define diml 20

std::ifstream f("lca.in");
std::ofstream g("lca.out");

int N, Q;
std::vector <int> son[dimn];
int neuler, euler[dimn*2];
int level[dimn*2], first[dimn];
int lg[dimn*2], rmq[diml][dimn*4];      //pt rmq, lucram cu repr euler

void dfs(int nod=1, int nivel=0) {
    euler[++neuler] = nod;
    level[neuler] = nivel;
    first[nod] = neuler;

    for (int i=0; i<son[nod].size(); i++) {
        dfs(son[nod][i], nivel+1);
        euler[++neuler] = nod;
        level[neuler] = nivel;
    }
}
void calc_rmq() {
    for (int i=2; i<=neuler; i++)
        lg[i] = lg[i>>1] + 1;
    for (int i=1; i<=neuler; i++)
        rmq[0][i] = i;

    for (int i=1, j, len; (1<<i) < neuler; i++)
        for (j=1; j<=neuler - (1<<i); j++) {
            len = 1<<(i - 1);
            rmq[i][j] = rmq[i-1][j];

            if(level[rmq[i-1][j+len]] < level[rmq[i][j]])
                rmq[i][j] = rmq[i-1][j+len];
        }
}
int min_interval(int a, int b) {
    int diff = b - a + 1;
    int len = lg[diff];
    int index = rmq[len][a];
    if(level[index] > level[rmq[len][a + diff - (1<<len)]])
        index = rmq[len][a + diff - (1<<len)];
    return index;
}

int lca(int x, int y) {
    int a = first[x], b = first[y];
    if(a>b) std::swap(a, b);
    int sol = min_interval(a, b);
    return euler[sol];
}

void citire() {
    f >> N >> Q;
    for (int i=1, x; i<N; i++) {
        f >> x;
        son[x].push_back(i+1);
    }
}
void rezolvare() {
    dfs();
    calc_rmq();

    int y, x;
    while(Q--) {
        f >> x >> y;
        g << lca(x, y) << "\n";
    }
}

int main()
{
    citire();
    rezolvare();

    return 0;
}