Cod sursa(job #1196764)

Utilizator RazvanR104Razvan-Andrei Ciocoiu RazvanR104 Data 9 iunie 2014 00:47:23
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.51 kb
#include <iostream>
#include <iomanip>
#include <fstream>

#include <algorithm>
#include <bitset>
#include <deque>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#if __cplusplus > 199711L
#include <unordered_map>
#include <unordered_set>
#endif

#include <cstdio>
#include <ctime>
#include <cmath>
#include <cstring>
#include <cstdlib>

using namespace std;

typedef long long int64;

ifstream fin("lca.in");
ofstream fout("lca.out");

const int NMAX = 100010;

int N, M, lvl, position;
int segm_tree[4 * NMAX], first[NMAX], pos[4 * NMAX];
vector<int> G[NMAX], nodes, level;

void DF(const int node, const int lvl)
{
    int it;
    nodes.push_back(node);
    level.push_back(lvl);
    first[node] = nodes.size() - 1;

    for (it = 0; it < (int)G[node].size(); ++it)
    {
        DF(G[node][it], lvl + 1);

        nodes.push_back(node);
        level.push_back(lvl);
    }
}

void build_tree(const int node, const int left, const int right)
{
    if (left == right)
    {
        segm_tree[node] = level[left - 1];
        pos[node] = left - 1;
        return;
    }

    int div = (left + right) >> 1;
    build_tree(node * 2, left, div);
    build_tree(node * 2 + 1, div + 1, right);

    if (segm_tree[node * 2] > segm_tree[node * 2 + 1])
    {
        segm_tree[node] = segm_tree[node * 2 + 1];
        pos[node] = pos[node * 2 + 1];
    }
    else
    {
        segm_tree[node] = segm_tree[node * 2];
        pos[node] = pos[node * 2];
    }
}

void query(const int node, const int left, const int right, const int qleft, const int qright)
{
    if (left >= qleft && right <= qright)
    {
        if (lvl > segm_tree[node])
        {
            lvl = segm_tree[node];
            position = pos[node];
        }
        return;
    }

    int div = (left + right) >> 1;
    if (qleft <= div) query(node * 2, left, div, qleft, qright);
    if (qright > div) query(node * 2 + 1, div + 1, right, qleft, qright);
}

int main()
{
    int i, x, y;

    fin >> N >> M;

    for (i = 2; i <= N; ++i)
    {
        fin >> x;
        G[x].push_back(i);
    }

    DF(1, 0);
    build_tree(1, 1, nodes.size());

    while(M--)
    {
        fin >> x >> y;
        if (first[x] > first[y]) swap(x, y);
        lvl = 1 << 30;
        query(1, 1, nodes.size(), first[x], first[y]);
        fout << nodes[position] << '\n';
    }

    fin.close();
    fout.close();
    return 0;
}