Cod sursa(job #1411158)

Utilizator cautionPopescu Teodor caution Data 31 martie 2015 14:52:14
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.88 kb
#include <fstream>
#include <vector>
#include <algorithm>
#define INF 666013
#define MAXN 350000
#define MAXLOGN 20
using namespace std;
long n, m, cur_lvl;
vector<long> *tree;
long euler[MAXLOGN][MAXN], ctr, v[MAXLOGN][MAXN], *first_euler;
void buildRMQ()
{
    long k, powk, i;
    for(k=1, powk=2; powk<=ctr; ++k, powk*=2)
        for(i=ctr-powk+1; i>=1; --i)
            if(v[k-1][i]<v[k-1][i+powk/2])
            {
                v[k][i]=v[k-1][i];
                euler[k][i]=euler[k-1][i];
            }
            else
            {
                v[k][i]=v[k-1][i+powk/2];
                euler[k][i]=euler[k-1][i+powk/2];
            }
}
long queryRMQ(long x, long y)
{
    long k=1, powk=2;
    while(powk<=y-x)
    {
        powk*=2;
        ++k;
    }
    --k; powk/=2;
    if(v[k][x]<v[k][y-powk+1])
        return euler[k][x];
    else return euler[k][y-powk+1];
}
long queryLCA(long x, long y)
{
    x=first_euler[x];
    y=first_euler[y];
    if(x>y) swap(x, y);
    return queryRMQ(x, y);
}
void pushEuler(long x)
{
    ++ctr;
    euler[0][ctr]=x;
    v[0][ctr]=cur_lvl;
    if(first_euler[x]>ctr)
        first_euler[x]=ctr;
}
void buildEuler(long x)
{
    pushEuler(x);
    for(vector<long>::iterator it=tree[x].begin(), ed=tree[x].end(); it!=ed; ++it)
    {
        ++cur_lvl;
        buildEuler(*it);
        --cur_lvl;
        pushEuler(x);
    }
}
int main()
{
    long i, dad, x, y;
    ifstream in("lca.in");
    ofstream out("lca.out");
    in>>n>>m;
    tree = new vector<long>[n+1];
    first_euler = new long[n+1];
    for(i=1; i<=n; ++i) first_euler[i]=INF;
    for(i=2; i<=n; ++i)
    {
        in>>dad;
        tree[dad].push_back(i);
    }
    cur_lvl=0;
    buildEuler(1);
    buildRMQ();
    for(i=0; i<m; ++i)
    {
        in>>x>>y;
        out<<queryLCA(x, y)<<'\n';
    }
    return 0;
}