Cod sursa(job #2635039)

Utilizator k2e0e0w3qDumitrescu Gheorghe k2e0e0w3q Data 13 iulie 2020 01:03:37
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.17 kb
#include <stdio.h>
#include <stdlib.h>
#define N 200000
#define log(x) 31 - __builtin_clz(x)

static const int b = 30; // ar trebui sa fie log(n) >> 1
int n, mask[N], first[N<<1], niv[N<<1],
    seg[log(N/b)+2][N], v[(N<<1)+1], size;

int cmp (int a, int b) {
    return niv[v[a]] < niv[v[b]] ? a : b;
}

int trans (int x, int base = b) {
    return x - (log(mask[x] & ((1 << base) - 1)));
}

int query (int x, int y) {
    if (y - x + 1 <= b)
        return v[trans(y, y-x+1)];
    int ans = cmp(trans(x + b - 1), trans(y));

    x /= b; ++x;
    y /= b; --y;
    if (x <= y) {
        int lg = log(y-x+1);
        ans = cmp(ans, cmp(seg[lg][x], seg[lg][y - (1<<lg) + 1]));
    }
    return v[ans];
}

struct nod {
    int inf;
    struct nod* urm;
} *G[N+1];

void add (int x, int i) {
    struct nod *e = (struct nod*) malloc(sizeof (struct nod));
    e->inf = i;
    e->urm = G[x];

    G[x] = e;
}

void dfs (int x, int from = 0) {
    v[size++] = x;

    struct nod* p = G[x];
    for (; p; p=p->urm)
        if (p->inf != from) {
            first[p->inf] = size;
            dfs(p->inf, x);
        }
    v[size++] = from;
}

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

    int q, i, j;
    scanf("%d%d", &n, &q);

    for (i=2; i<=n; ++i) {
        scanf("%d", &j);
        niv[i] = niv[j] + 1;
        add(j, i);
    }
    dfs(1);

    n = size;
    int at = 0;
    for (i=0; i<n; ++i) {
        at = (at << 1) & ((1<<b) - 1);
        while (at && cmp(i, i - __builtin_ctz(at)) == i)
            at ^= at & -at;
        at |= 1;
        mask[i] = at;
    }

    n /= b;
    for (i=0; i<n; ++i)
        seg[0][i] = trans(b*i + b - 1);

    for (i=1; (1<<i) <= n; ++i)
        for (j=0; j + (1<<i) <= n; ++j)
            seg[i][j] = cmp(seg[i-1][j], seg[i-1][j + (1<<i-1)]);

    int x, y, ans;
    for (; q; --q) {
        scanf("%d%d", &x, &y);
        x = first[x];
        y = first[y];
        if (x > y) {
            i = x;
            x = y;
            y = i;
        }

        ans = query(x, y);
        printf("%d\n", ans);
    }
    return 0;
}