Cod sursa(job #1404228)

Utilizator andreiblaj17Andrei Blaj andreiblaj17 Data 27 martie 2015 22:03:38
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.95 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#define nmax 100005

using namespace std;

int n, m;
int Euler[2 * nmax], P[nmax], Exp[2 * nmax], Min[19][2 * nmax], Pos[19][2 * nmax], Nivel[nmax];
vector <int> G[nmax];

void euler(int nod)
{
    Euler[++Euler[0]] = nod;
    P[nod] = Euler[0];
    for (int i = 0; i < G[nod].size(); i++)
    {
        Nivel[G[nod][i]] = Nivel[nod] + 1;
        euler(G[nod][i]);
        Euler[++Euler[0]] = nod;
    }
}

void preprocess()
{
    Exp[1] = 0;
    for (int i = 2; i <= Euler[0]; i++)
        Exp[i] = Exp[i/2] + 1;
    
    for (int i = 1; i <= Euler[0]; i++)
    {
        Min[0][i] = Nivel[Euler[i]];
        Pos[0][i] = i;
    }
    
    for (int i = 1; i <= Exp[Euler[0]]; i++)
        for (int j = 1; j <= Euler[0] - (1<<i) + 1; j++)
        {
            int st = j;
            int dr = st + (1<<i) - 1;
            int mid = dr - (1<<(i-1)) + 1;
            
            Min[i][j] = Min[i-1][st];
            Pos[i][j] = Pos[i-1][st];
            
            if (Min[i][j] > Min[i-1][mid])
            {
                Min[i][j] = Min[i-1][mid];
                Pos[i][j] = Pos[i-1][mid];
            }
            
        }
}

int main()
{
    
    ifstream fi("lca.in");
    ofstream fo("lca.out");
    
    fi >> n >> m;
    
    for (int i = 2; i <= n; i++)
    {
        int x;
        fi >> x;
        G[x].push_back(i);
    }
    
    euler(1);
    preprocess();
    
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        fi >> x >> y;
        
        x = P[x], y = P[y];
        
        if (x > y)
            swap(x, y);
        
        int l = y - x + 1;
        int k = Exp[l];
        
        int rez = Min[k][x];
        int lca = Euler[Pos[k][x]];
        
        x = y - (1<<k) + 1;
        
        if (rez > Min[k][x])
            lca = Euler[Pos[k][x]];
        
        fo << lca << "\n";
        
    }
    
    fi.close();
    fo.close();
    
    return 0;
}

// 3 2 1 2 2