Cod sursa(job #1200458)

Utilizator mircea.dobreanuMircea Dobreanu mircea.dobreanu Data 22 iunie 2014 15:21:43
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.71 kb
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 100005;
ifstream fin("lca.in");
ofstream fout("lca.out");
vector<int> G[MAXN];
int E[2*MAXN], pos[MAXN], lvl[MAXN], lg[MAXN];
int RMQ[15][2*MAXN];
int n, m, lge;

void dfs(int u, int current_lvl)
{
    E[++lge] = u;
    lvl[lge] = current_lvl;

    pos[u] = min(pos[u], lge);

    for (int v : G[u])
    {
        dfs(v, current_lvl+1);
        E[++lge] = u;
        lvl[lge] = current_lvl;
    }
}


void rmq()
{
    //Base case RMQ TODO
    for (int j=1; j<=lge; ++j)
        RMQ[0][j] = j;
    //Precompute RMQ
    for (int i=1; (1<<i) <= lge; ++i)
    {
        for (int j=1; j<=lge-(1<<i)+1; ++j)
        {
            if (lvl[RMQ[i-1][j]] <= lvl[RMQ[i-1][j+(1<<(i-1))]])
                RMQ[i][j] = RMQ[i-1][j];
            else
                RMQ[i][j] = RMQ[i-1][j+(1<<(i-1))];
        }
    }
}

int main()
{
    fin>>n>>m;
    for (int parent=0, node = 2; node <= n; ++node)
    {
        fin>>parent;
        G[parent].push_back(node);
    }

    //Set first appearance to infinity
    for (int i=0; i<=n; ++i)
        pos[i] = MAXN;

    //Eulerian representation
    dfs(1, 0);

    //Preprocess RMQ
    rmq();


    //Precalculate the log
    lg[1]=0;
    for (int i=2; i<=lge; ++i)
        lg[i]=lg[i/2]+1;



    //Handle the queries
    int u, v;
    for (int k=1; k<=m; ++k)
    {
        fin>>u>>v;
        int start = min(pos[u], pos[v]), finish = max(pos[u], pos[v]);
        int diff = finish - start;

        int ancestor = E[min(RMQ[lg[diff]][start], RMQ[lg[diff]][finish-(1<<lg[diff])+1])];
        fout<<ancestor<<'\n';

    }
    return 0;
}