Cod sursa(job #2702979)

Utilizator raducostacheRadu Costache raducostache Data 6 februarie 2021 14:40:37
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.07 kb
#include <stdio.h>
#include <vector>

#define NMAX 100005

using namespace std;

int n, Q, root, parent[NMAX];
bool viz[NMAX];
int pmin, pe, euler[NMAX * 4], depth[NMAX * 4], fa[NMAX * 4], arbMin[NMAX * 16];
vector <int> G[NMAX];

void dfs(int, int);
int lca(int, int);
void update(int, int, int, int);
void Query(int, int, int, int, int);

int main() {
    FILE *f = fopen("lca.in", "r");
    FILE *g = fopen("lca.out", "w");

    fscanf(f, "%d %d\n", &n, &Q);
    root = 1;
    for (int i = 2; i <= n; ++i) {
        fscanf(f, "%d", parent+i);
        G[i].push_back(parent[i]);
        G[parent[i]].push_back(i);
    }
    dfs(root, 1);
    for (int i = 1; i <= pe; ++i) {
        update(i, 1, 1, pe);
        if(fa[euler[i]] == 0)
            fa[euler[i]] = i;
    }
    while (Q--) {
        int a, b;
        fscanf(f, "%d %d\n", &a, &b);
        fprintf(g, "%d\n", lca(a, b));
    }
    return 0;
}

void dfs(int node, int level) {
    depth[++pe] = level;
    euler[pe] = node;
    viz[node] = 1;
    for (auto it:G[node]) {
        if (viz[it] == 0) {
            dfs(it, level + 1);
            depth[++pe] = level;
            euler[pe] = node;
        }
    }
}

int lca(int a, int b) {
    pmin = fa[a];
    int st = fa[a];
    int dr = fa[b];
    if(st > dr)
        swap(st, dr);
    Query(st, dr, 1, 1, pe);
    return euler[pmin];
}

void update(int p, int node, int left, int right) {
    if(left == right) {
        arbMin[node] = p;
        return;
    }
    if(depth[p] < depth[arbMin[node]] || depth[arbMin[node]] == 0)
        arbMin[node] = p;
    int mid = (left + right) / 2;
    if(p <= mid)
        update(p, 2 * node, left, mid);
    else
        update(p, 2 * node + 1, mid + 1, right);
}

void Query(int qLeft, int qRight, int node, int left, int right) {
    if(left >= qLeft && right <= qRight) {
        if(depth[arbMin[node]] < depth[pmin])
            pmin = arbMin[node];
        return;
    }
    int mid = (left + right) / 2;
    if (qLeft <= mid)
        Query(qLeft, qRight, 2 * node, left, mid);
    if(qRight > mid)
        Query(qLeft, qRight, 2 * node + 1, mid + 1, right);

}