Cod sursa(job #3232314)

Utilizator Dynamate921Catalin Moldoveanu Dynamate921 Data 29 mai 2024 21:30:45
Problema Lowest Common Ancestor Scor 100
Compilator c-64 Status done
Runda Arhiva educationala Marime 3.36 kb
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAXN 100001

typedef struct {
    int *data;
    int size;
    int capacity;
} Vector;

void initVector(Vector *v, int capacity) {
    v->data = (int *)malloc(capacity * sizeof(int));
    v->size = 0;
    v->capacity = capacity;
}

void pushBack(Vector *v, int value) {
    if (v->size == v->capacity) {
        v->capacity *= 2;
        v->data = (int *)realloc(v->data, v->capacity * sizeof(int));
    }
    v->data[v->size++] = value;
}

typedef struct {
    int *first;
    int *euler;
    int *height;
    int **rmq;
    int eulerIndex;
    int n;
} LCA;

void dfs(LCA *lca, Vector *tree, int node, int h) {
    lca->first[node] = lca->eulerIndex;
    lca->height[lca->eulerIndex] = h;
    lca->euler[lca->eulerIndex++] = node;

    for (int i = 0; i < tree[node].size; ++i) {
        int nextNode = tree[node].data[i];
        if (lca->first[nextNode] == -1) {
            dfs(lca, tree, nextNode, h + 1);
            lca->euler[lca->eulerIndex] = node;
            lca->height[lca->eulerIndex++] = h;
        }
    }
}

void buildRMQ(LCA *lca) {
    int m = 2 * lca->n - 1;
    int logm = (int)log2(m) + 1;

    lca->rmq = (int **)malloc(m * sizeof(int *));
    for (int i = 0; i < m; ++i) {
        lca->rmq[i] = (int *)malloc(logm * sizeof(int));
        lca->rmq[i][0] = i;
    }

    for (int j = 1; (1 << j) <= m; ++j) {
        for (int i = 0; i + (1 << j) - 1 < m; ++i) {
            int first = lca->rmq[i][j - 1];
            int second = lca->rmq[i + (1 << (j - 1))][j - 1];
            lca->rmq[i][j] = (lca->height[first] < lca->height[second]) ? first : second;
        }
    }
}

int queryRMQ(LCA *lca, int left, int right) {
    int length = right - left + 1;
    int logLength = (int)log2(length);

    int first = lca->rmq[left][logLength];
    int second = lca->rmq[right - (1 << logLength) + 1][logLength];
    return (lca->height[first] < lca->height[second]) ? first : second;
}

int findLCA(LCA *lca, int u, int v) {
    if (lca->first[u] > lca->first[v]) {
        int temp = u;
        u = v;
        v = temp;
    }
    int left = lca->first[u];
    int right = lca->first[v];
    int index = queryRMQ(lca, left, right);
    return lca->euler[index];
}

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

    int n, m;
    fscanf(in, "%d %d", &n, &m);

    Vector tree[MAXN];
    for (int i = 1; i <= n; ++i) {
        initVector(&tree[i], 2);
    }

    for (int i = 2; i <= n; ++i) {
        int parent;
        fscanf(in, "%d", &parent);
        pushBack(&tree[parent], i);
    }

    LCA lca;
    lca.n = n;
    lca.euler = (int *)malloc(2 * n * sizeof(int));
    lca.first = (int *)malloc((n + 1) * sizeof(int));
    lca.height = (int *)malloc(2 * n * sizeof(int));

    for (int i = 1; i <= n; ++i) {
        lca.first[i] = -1;
    }

    lca.eulerIndex = 0;
    dfs(&lca, tree, 1, 0);

    buildRMQ(&lca);

    for (int i = 0; i < m; ++i) {
        int u, v;
        fscanf(in, "%d %d", &u, &v);
        int lcaNode = findLCA(&lca, u, v);
        fprintf(out, "%d\n", lcaNode);
    }

    fclose(in);
    fclose(out);

    // Free allocated memory
    free(lca.euler);
    free(lca.first);
    free(lca.height);
    for (int i = 0; i < 2 * n - 1; ++i) {
        free(lca.rmq[i]);
    }
    free(lca.rmq);

    for (int i = 1; i <= n; ++i) {
        free(tree[i].data);
    }

    return 0;
}