Cod sursa(job #2216693)

Utilizator axelteoTeodor Dutu axelteo Data 27 iunie 2018 18:11:02
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.92 kb
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

#define MAX_N 100001
#define MAX_SIZE 200001
#define MAX_RMQ 400001
#define MAX_LOG 18

ifstream fIn("lca.in");
ofstream fOut("lca.out");

int euler[MAX_SIZE], level[MAX_SIZE], pos[MAX_N], rmq[MAX_RMQ][MAX_LOG], lg[MAX_SIZE];
int numNodes, numQueries, p;
vector<vector<int>> adjList(MAX_N);

void generateVectors(int currNode, int currLevel) {
    euler[p] = currNode;
    level[p] = currLevel;
    pos[currNode] = p++;

    for (auto nextNode : adjList[currNode]) {
        generateVectors(nextNode, currLevel+1);

        euler[p] = currNode;
        level[p++] = currLevel;
    }
}

void buildRmqAndLog() {
    for (register int i = 2; i <= p; ++i) {
        lg[i] = lg[i >> 1] + 1;
    }

    for (register int i = 0; i < p; ++i) {
        rmq[i][0] = i;
    }

    auto logP = (int)log2((double)p);

    for (register int j = 1; j <= logP; ++j) {
        int lim = p - (1 << j);

        for (register int i = 0; i < lim; ++i) {
            int k = (1 << (j - 1));

            rmq[i][j] = level[rmq[i][j - 1]] < level[rmq[i + k][j - 1]] ?
                        rmq[i][j - 1] : rmq[i + k][j - 1];
        }
    }
}

int main() {
    int nodeX, nodeY;

    fIn >> numNodes >> numQueries;

    for (register int i = 2; i <= numNodes; ++i) {
        fIn >> nodeX;
        adjList[nodeX].push_back(i);
    }

    generateVectors(1, 0);
    buildRmqAndLog();

    for (register int i = 0; i < numQueries; ++i) {
        fIn >> nodeX >> nodeY;

        int posX = pos[nodeX];
        int posY = pos[nodeY];

        if (posX > posY) {
            swap(posX, posY);
        }

        int len = posY - posX + 1;
        int k = lg[len];
        int diff = len - (1 << k);

        int sol = level[rmq[posX][k]] < level[rmq[posX + diff][k]] ?
                  rmq[posX][k] : rmq[posX + diff][k];

        fOut << euler[sol] << '\n';
    }

    fIn.close();
    fOut.close();

    return 0;
}