Cod sursa(job #1200470)

Utilizator mircea.dobreanuMircea Dobreanu mircea.dobreanu Data 22 iunie 2014 15:51:53
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.13 kb
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 200005;
ifstream fin("lca.in");
ofstream fout("lca.out");
vector<int> G[MAXN];
int E[MAXN], pos[MAXN], lvl[MAXN], lg[MAXN];
int RMQ[20][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
    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;


        // E PE LEVELE BOULE!!!
        //int ancestor = E[min(RMQ[lg[diff]][start], RMQ[lg[diff]][finish-(1<<lg[diff])+1])];

        //We separate an interval into 2 largest possible intervals
        //that have 2^z elements. One starts at the beginning at one finishes at the end
        int ancestor;
        if (lvl[RMQ[lg[diff]][start]] <= lvl[RMQ[lg[diff]][finish-(1<<lg[diff])+1]])
            ancestor = E[RMQ[lg[diff]][start]];
        else
            ancestor = E[RMQ[lg[diff]][finish-(1<<lg[diff])+1]];

        fout<<ancestor<<'\n';

    }
    return 0;
}