Cod sursa(job #2151200)

Utilizator MaligMamaliga cu smantana Malig Data 4 martie 2018 11:15:22
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.15 kb
#include <bits/stdc++.h>

using namespace std;

#if 1
    #define pv(x) cout<<#x<<" = "<<x<<"; ";cout.flush()
    #define pn cout<<endl
#else
    #define pv(x)
    #define pn
#endif

#ifdef ONLINE_JUDGE
    #define in cin
    #define out cout
#else
    ifstream in("lca.in");
    ofstream out("lca.out");
#endif

using ll = long long;
using ull = unsigned long long;
using ui = unsigned int;
#define pb push_back
#define mp make_pair
const int NMax = 2e5 + 5;
const ll inf_ll = 1e18 + 5;
const int inf_int = 1e9 + 5;
const int mod = 100003;
using zint = int;

int N,M,nrEuler;
int depth[NMax],position[NMax],euler[NMax],lg[NMax],rmq[NMax][20],dist[NMax];
vector< int > v[NMax], oldRed, newRed;

struct queryType {
    int tip, node;
};
vector< queryType > bucket;

void buildEuler(int node, int dad) {
    euler[++nrEuler] = node;
    position[node] = nrEuler;
    depth[node] = depth[dad] + 1;

    for (int nxt : v[node]) {
        if (nxt == dad) {
            continue;
        }

        buildEuler(nxt, node);
        euler[++nrEuler] = node;
    }
}

int lca(int a, int b) {
    a = position[a];
    b = position[b];

    if (a > b) {
        swap(a,b);
    }

    int len = b-a+1, pw = lg[len];
    int node1 = rmq[a][pw], node2 = rmq[b - (1<<pw) + 1][pw];

    return (depth[node1] < depth[node2]) ? node1 : node2;
}

int main() {
    cin.sync_with_stdio(false);
    cin.tie(0);

    in >> N >> M;
    for (int i = 2;i <= N;++i) {
        int dad;
        in >> dad;

        v[dad].pb(i);
        v[i].pb(dad);
    }

    buildEuler(1,0);

    rmq[1][0] = euler[1];
    lg[1] = 0;
    for (int i = 2;i <= nrEuler;++i) {
        rmq[i][0] = euler[i];
        lg[i] = lg[i/2] + 1;
    }

    for (int p = 1;(1<<p) <= nrEuler;++p) {

        for (int i = 1;i + (1<<p) - 1 <= nrEuler;++i) {
            int node1 = rmq[i][p-1],
                node2 = rmq[i + (1<<(p-1))][p-1];

            rmq[i][p] = (depth[node1] < depth[node2]) ? node1 : node2;
        }
    }

    while (M--) {
        int x,y;
        in >> x >> y;
        out << lca(x,y) << '\n';
    }

    return 0;
}