Cod sursa(job #2283876)

Utilizator mihaicivMihai Vlad mihaiciv Data 15 noiembrie 2018 23:16:03
Problema Lowest Common Ancestor Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.26 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

void Euler(int currentNode, vector<int> a[], int euler[], int &currentSize) {
    euler[currentSize] = currentNode;
    currentSize ++;

    for (int i = 0; i < a[currentNode].size(); ++i) {
        int currentChild = a[currentNode][i];
        Euler(currentChild, a, euler, currentSize);
        euler[currentSize] = currentNode;
        currentSize ++;
    }
}

void createHeight(int currentNode, vector <int> a[], int height[], int currentHeight) {
    height[currentNode] = currentHeight;
    for (int i = 0; i <  a[currentNode].size(); ++i) {
        int currentChild = a[currentNode][i];
        createHeight(currentChild, a, height, currentHeight + 1);
    }
}

void createRMQ(int n, int **RMQ, int height[], int euler[], int eSize, int firstAppearPosition[], int **pRMQ) {

    int put[30]; /// put[i] = 2 ^ i;

    put[0] = 1;

    int lgmax = 0;
    for (int i = 1; 2 * put[i - 1] <= eSize; ++i) {
        put[i] = 2 * put[i - 1];
        lgmax ++;
    }

    for (int i = 0; i < eSize; ++i) {
        RMQ[i][0] = height[euler[i]];
        pRMQ[i][0] = euler[i];
    }

    for (int j = 1; j <= lgmax; ++j) {
        for (int i = 0; i + put[j - 1] < eSize; ++i) {
            RMQ[i][j] = RMQ[i][j - 1];
            pRMQ[i][j] = pRMQ[i][j - 1];
            if ( RMQ[i][j - 1] > RMQ[i + put[j - 1]][j - 1] ) {
                RMQ[i][j] = RMQ[i + put[j - 1]][j - 1];
                pRMQ[i][j] = pRMQ[i + put[j - 1]][j - 1];
            }
        }

    }
}

int lca(int x, int y, int euler[], int **RMQ, int firstAppearPosition[], int **pRMQ) {
    if (firstAppearPosition[x] > firstAppearPosition[y]) { swap(x, y); }
    int p = 0;
    while ( (1 << p) < ( firstAppearPosition[y] - firstAppearPosition[x] + 1) ) {
        p ++;
    }
    p --;

    int pminim = pRMQ[firstAppearPosition[x]][p];

    if ( RMQ[firstAppearPosition[x]][p] > RMQ[firstAppearPosition[y] - (1 << p) ][p] ) {
        pminim = pRMQ[firstAppearPosition[y] - (1 << p) ][p];
    }

    return pminim;
}

int main() {

    ifstream f("lca.in");
    ofstream g("lca.out");

    int n, m;

    f >> n >> m;

    vector <int> a[n + 1];

    for (int i = 0; i < n; ++i) {
        a[i + 1].clear();
    }

    for (int i = 2; i <= n; ++i) {
        int current_father;
        f >> current_father;
        a[current_father].push_back(i);
    }

    int euler[5 * n], height[n + 1];
    int eSize = 0;

    Euler(1, a, euler, eSize);
    createHeight(1, a, height, 0);

    int firstAppearPosition[n + 1];

    for (int i = 0; i <= n; ++i) {
        firstAppearPosition[i] = -1;
    }

    for (int i = 0; i < eSize; ++i) {
        if ( firstAppearPosition[euler[i]] == -1 ) {
            firstAppearPosition[euler[i]] = i;
        }
    }

    int **RMQ = new int*[eSize + 1];
    int **pRMQ = new int*[eSize + 1];
    for (int i = 0; i <= eSize; ++i) {
        RMQ[i] = new int[20];
        pRMQ[i] = new int[20];
    }

    createRMQ(n + 1, RMQ, height, euler, eSize, firstAppearPosition, pRMQ);


    while (m --) {
        int x, y;
        f >> x >> y;
        g << lca(x, y, euler, RMQ, firstAppearPosition, pRMQ) << "\n";
    }

    return 0;
}