Cod sursa(job #1905249)

Utilizator vianulegendsTudor Vianu vianulegends Data 5 martie 2017 23:08:02
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.45 kb
#include <stdio.h>

struct node {
    int v;
    node *n;
};
node* all() {
    static int sp = 1000;
    static node* st = NULL;
    if (sp == 1000) {
        sp = 0;
        st = new node[1000];
    }
    return st + (sp++);
}

namespace Var {
    FILE *fin, *fout;
    int N, M;
    node **G;
    int e, *euler;
    int *lvl, *fi;
    int *lg, **m;
};

void citire() {
    using namespace Var;
    fscanf(fin, "%d%d", &N, &M);
    G = new node*[N + 1]();
    for (int i = 2; i <= N; ++i) {
        int x;
        fscanf(fin, "%d", &x);
        node *edge = all();
        edge->v = i;
        edge->n = G[x];
        G[x] = edge;
    }
    euler = new int[2*N - 1];
    lvl = new int[N + 1];
    fi = new int[N + 1];
}
void f_euler(int u = 1, int dep = 0) {
    using namespace Var;
    lvl[u] = dep;
    fi[u] = e;
    euler[e++] = u;
    for (node* it = G[u]; it; it = it->n) {
        f_euler(it->v, dep + 1);
        euler[e++] = u;
    }
}
int mi(int x, int y) {
    using namespace Var;
    return (lvl[euler[x]] < lvl[euler[y]] ? x : y);
}
void pre_rmq() {
    using namespace Var;
    // Fac vectorul lg
    lg = new int[e + 1];
    lg[1] = 0;
    for (int i = 2; i <= e; ++i) {
        lg[i] = 1 + lg[i / 2];
    }
    // Fac tabloul m
    m = new int*[lg[e] + 1];
    for (int i = 0; i <= lg[e]; ++i) {
        m[i] = new int[e];
    }
    for (int i = 0; i <= e; ++i) {
        m[0][i] = i;
    }
    for (int i = 1; i <= lg[e]; ++i) {
        for (int j = 0; j < e; ++j) {
            if (j + (1 << (i-1)) < e) {
                m[i][j] = mi(m[i-1][j], m[i-1][j + (1<<(i-1))]);
            } else {
                m[i][j] = m[i-1][j];
            }
        }
    }
}
int rmq(int l, int r) {
    using namespace Var;
    return mi(m[lg[r - l + 1]][l], m[lg[r - l + 1]][r - (1 << lg[r-l+1]) + 1]);
}
int lca(int x, int y) {
    using namespace Var;
    if (fi[x] < fi[y]) {
        return euler[rmq(fi[x], fi[y])];
    } else {
        return euler[rmq(fi[y], fi[x])];
    }
}
void afisare() {
    using namespace Var;
    for (int i = 0; i < M; ++i) {
        int x, y;
        fscanf(fin, "%d%d", &x, &y);
        fprintf(fout, "%d\n", lca(x, y));
    }
}

int main()
{
    using namespace Var;
    fin = fopen("lca.in", "r");
    fout = fopen("lca.out", "w");

    citire();
    f_euler();
    pre_rmq();
    afisare();

    fclose(fin);
    fclose(fout);
    return 0;
}