Cod sursa(job #2408408)

Utilizator FunnyStockyMihnea Andreescu FunnyStocky Data 17 aprilie 2019 22:07:29
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.45 kb
#include <cstdio>
#include <cctype>
#include <vector>

using namespace std;

const int SIZE = 1 << 17;
int pointer = SIZE;
char buffer[SIZE];

char Advance() {
        if(pointer == SIZE) {
                fread(buffer, 1, SIZE, stdin);
                pointer = 0;
        }
        return buffer[pointer++];
}

int Read() {
        int answer = 0;
        char ch = Advance();
        while(!isdigit(ch)) {
                ch = Advance();
        }
        while(isdigit(ch)) {
                answer = answer * 10 + ch - '0';
                ch = Advance();
        }
        return answer;
}

const int N = 100000 + 7;
const int LG = 19;

int n, t;
vector <int> g[N];
int dep[N];
int euler[3 * N], top;
int first[N], last[N];

struct kek {
        int fi;
        int se;
};

kek rmq[3 * N][LG];
int mylog[3 * N];

void __read() {
        n = Read();
        t = Read();
        for(int i = 2; i <= n; i++) {
                int dad = Read();
                g[dad].push_back(i);
        }
}

void build(int nod) {
        euler[++top] = nod;
        first[nod] = last[nod] = top;
        for(auto &nou : g[nod]) {
                dep[nou] = 1 + dep[nod];
                build(nou);
                euler[++top] = nod;
                last[nod] = top;
        }
}

kek Min(kek a, kek b) {
        if(a.fi < b.fi) {
                return a;
        } else {
                return b;
        }
}

void buildRMQ() {
        for(int i = 2; i <= top; i++) {
                mylog[i] = 1 + mylog[i / 2];
        }
        for(int i = 1; i <= top; i++) {
                rmq[i][0] = {dep[euler[i]], i};
        }
        for(int k = 1; (1 << k) <= top; k++) {
                for(int i = 1; i + (1 << k) - 1 <= top; i++) {
                        rmq[i][k] = Min(rmq[i][k - 1], rmq[i + (1 << (k - 1))][k - 1]);
                }
        }
}

int lca(int a, int b) {
        int st = last[a];
        int dr = first[b];
        if(st > dr) {
                swap(st, dr);
        }
        int k = mylog[dr - st + 1];
        kek sol = Min(rmq[st][k], rmq[dr - (1 << k) + 1][k]);
        return euler[sol.se];
}

int main() {
        freopen("lca.in", "r", stdin);
        freopen("lca.out", "w", stdout);
        __read();
        build(1);
        buildRMQ();
        while(t--) {
                int a = Read(), b = Read();
                printf("%d\n", lca(a, b));
        }
        return 0;
}