Cod sursa(job #2788269)

Utilizator Matei_PanzariuMatei Panzariu Matei_Panzariu Data 25 octombrie 2021 13:59:24
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.83 kb

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

#define DIM 210000

vector <vector <int> > Graph;
int VEuler[DIM], FirstApp[DIM], N, Q, x, y, rmq[20][DIM << 1], L[DIM];

void Euler(int nod, int level);

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

    scanf("%d %d\n", &N, &Q);

    Graph.resize(N + 1);

    for(int i = 2; i <= N; ++i) {
        scanf("%d", &x);

        Graph[x].push_back(i);
    }

    Euler(1, 0);
    for(int i = 1; i <= VEuler[0]; ++i) {
        rmq[0][i] = i;
        //cout << VEuler[i] << ' ';
    }



    for(int i = 1; (1 << i) < VEuler[0]; ++i) {
        for(int j = 1; j <= VEuler[0] - (1 << i); ++j) {
            int l = 1 << (i - 1);
            rmq[i][j] = rmq[i - 1][j];
            if(L[rmq[i - 1][j + l]] < L[rmq[i][j]]) {
                rmq[i][j] = rmq[i - 1][j + l];
            }
        }
    }
    while(Q) {
        --Q;

        scanf("%d %d\n", &x, &y);

        x = FirstApp[x];
        y = FirstApp[y];

        if(x > y) {
            swap(x, y);
        }

        int diff = y - x + 1;
        int p=1;
        int exp=0;
        while(p<=diff)
        {
            p*=2;
            exp++;
        }
        p/=2;
        exp--;
        int sol = rmq[exp][x];
        int sh = diff - (1 << exp);
        if(L[sol] > L[rmq[exp][x + sh]]) {
            sol = rmq[exp][x + sh];
        }

        cout << VEuler[sol] << '\n';
    }
    return 0;
}

void Euler(int nod, int level) {
    VEuler[++VEuler[0]] = nod;
    FirstApp[nod] = VEuler[0];
    L[VEuler[0]] = level;

    for(unsigned int z = 0; z < Graph[nod].size(); ++z) {
        Euler(Graph[nod][z], level + 1);
        VEuler[++VEuler[0]] = nod;
        L[VEuler[0]] = level;
    }
}