Cod sursa(job #2084992)

Utilizator netfreeAndrei Muntean netfree Data 9 decembrie 2017 14:49:04
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.41 kb
#include <bits/stdc++.h>

using namespace std;

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

const int N_MAX = 100005;

int n, m;
int euler[3 * N_MAX], ne;
int poz[3 * N_MAX], niv[3 * N_MAX];
int dp[3 * N_MAX][30];

vector<int> vec[N_MAX];

void make_euler(int nod, int nivel){
    euler[++ne] = nod;
    niv[ne] = nivel;
    poz[nod] = ne;
    for(auto v : vec[nod]){
        make_euler(v, nivel + 1);
        euler[++ne] = nod;
        niv[ne] = nivel;
    }
}

void init() {
    for(int i = 1; i <= ne; i++)
          dp[i][0] = i;

    for(int j = 1; (1 << j) <= ne; j++)
          for(int i = 1; i + (1 << j) - 1 <= ne; i++)
              if (niv[dp[i][j - 1]] < niv[dp[i + (1 << (j - 1))][j - 1]])
                  dp[i][j] = dp[i][j - 1];
              else
                  dp[i][j] = dp[i + (1 << (j - 1))][j - 1];
}

int query(int i, int j){
    int k = log2(j - i + 1);
    if(niv[dp[i][k]] <= niv[dp[j - (1 << k) + 1][k]])
        return dp[i][k];
    return dp[j - (1 << k) + 1][k];
}

int lca(int a, int b){
    int lo = min(a, b);
    int hi = max(a, b);
    return euler[query(lo, hi)];
}

int main()
{
    fin >> n >> m;
    for(int i = 2, x; i<=n; ++i){
        fin >> x; vec[x].push_back(i);
    }
    make_euler(1, 0);

    init();

    while(m--){
        int a, b; fin >> a >> b;
        fout << lca(poz[a],poz[b]) << "\n";
    }
    return 0;
}