Cod sursa(job #2355388)

Utilizator mihai_brodschiMihai Brodschi mihai_brodschi Data 26 februarie 2019 01:06:25
Problema Lowest Common Ancestor Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.95 kb
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <unordered_map>

using namespace std;

struct euler {
    int v;
    euler *ts;

    euler() {
        v = 0;
        ts = nullptr;
    }
};

struct ends {
    euler *first;
    euler *last;

    ends() {
        first = nullptr;
        last = nullptr;
    }
};

int main() {
    euler e1, *aux;
    if (freopen("lca.in", "r", stdin) == nullptr) {
        return 1;
    }
    freopen("lca.out", "w", stdout);
    int n, m, k = 1;
    int *p = new int[200001]();
    scanf("%d %d\n", &n, &m);
    euler* e = new euler[2 * n + 1]();
    ends* inst = new ends[n + 1]();
    //citesc vector parinti
    for (int i = 1; i < n; i++)
        scanf("%d", &p[i + 1]);
    //parcurgere euler
    for (int i = 2; i <= n; i++) {
        //daca nu exista nodul parinte in parcurgere
        if (inst[p[i]].first == nullptr) {
            //adaug nodul parinte la sfarsitul vectorului parcurgere si salvez prima si ultima aparitie a nodului
            e[k].v = p[i];
            inst[e[k].v].first = &e[k];
            inst[e[k].v].last = &e[k];
            k++;
        }
        //daca nu exista nodul subordonat in parcurgere
        if (inst[i].first == nullptr) {
            //adaug nodul subordonat la sfarsitul vectorului parcurgere si salvez prima si ultima aparitie a nodului
            e[k].v = i;
            inst[e[k].v].first = &e[k];
            inst[e[k].v].last = &e[k];
            k++;
        }
        aux = (*(inst[p[i]].last)).ts;
        (*(inst[p[i]].last)).ts = inst[i].first;
        e[k].v = p[i];
        e[k].ts = aux;
        inst[e[k].v].last = &e[k];
        k++;
        (*(inst[i].last)).ts = inst[p[i]].last;
    }
    e1 = *inst[1].first;
    p[1] = 0;
    for (int i = 2; i <= 2 * n + 1; i++) {
        p[i] = p[i / 2] + 1;
    }
    delete[] inst;
    int** a = new int*[p[2 * n + 1]];
    a[0] = new int[2 * n + 1];
    int c = 0;
    unordered_map<int, int> *map = new unordered_map<int, int>;
    while (e1.ts != nullptr) {
        e1 = *e1.ts;
        a[0][c] = e1.v;
        if (map->find(e1.v) == map->end()) {
            map->insert(make_pair(e1.v, c));
        }
        // printf("%d ", e1.v);
        c++;
    }
    delete[] e;
    int r = 1;
    for (int i = 1; i < p[c]; i++) {
        r *= 2;
        a[i] = new int[c - r + 1];
        for (int j = 0; j < c - r + 1; j++) {
            a[i][j] = min(a[i - 1][j], a[i - 1][j + r / 2]);
        }
    }
    int n1, n2;
    for (int i = 0; i < m; i++) {
        scanf("%d %d", &n1, &n2);
        n1 = map->at(n1);
        n2 = map->at(n2);
        if (n1 > n2) {
            swap(n2, n1);
        }
        r = 1 << p[n2 - n1 + 1];
        printf("%d\n", min(a[p[n2 - n1 + 1]][n1], a[p[n2 - n1 + 1]][n2 - r + 1]));
    }
    for (int i = 0; i < p[c]; i++) {
        delete[] a[i];
    }
    delete[] p;
    delete[] a;
    delete map;
    return 0;
}