Cod sursa(job #1984407)

Utilizator hanganflorinHangan Florin hanganflorin Data 24 mai 2017 19:17:34
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.55 kb
#include <fstream>
#include <stdio.h>
#include <vector>
using namespace std;

ifstream is("lca.in");
ofstream os("lca.out");
//FILE* is = fopen("lca.in", "r");
//FILE* os = fopen("lca.out", "w");

int n, m, nr;
vector<vector<int> > G;
vector<int> euler, depth, first, K;
int M[500001][20];

void Read();
void Euler(int x, int d = 0);
void RMQ();
int Query(int a, int b);
int lca(int x, int y);
void Preprocesare();

int main()
{
    Read();
    euler.push_back(0);
    Euler(1);
    nr = euler.size()-1;
    Preprocesare();
    RMQ();
/*
    for ( int i = 1; i <= nr; ++i )
        os << euler[i] << " ";
    os << "\n";
    for ( int i = 1; i <= nr; ++i )
        os << depth[euler[i]] << " ";
    os << "\n";

    for ( int i = 1; i <= nr; ++i )
    {
        for ( int j = 0; j <= nr; ++j )
            os << M[i][j] << ' ';
        os << '\n';
    }

    return 0;
    */
    for ( int i = 0, x, y; i < m; ++i )
    {
        is >> x >> y;
        //fscanf(is, "%d%d", &x, &y);
        //fprintf(os, "%d\n", lca(x, y));
        os << lca(x, y) << "\n";
    }

    //fclose(is);
    //fclose(os);
    is.close();
    os.close();
    return 0;
}
void Read()
{
    is >> n >> m;
    //fscanf(is, "%d%d", &n, &m);
    G.resize(n+1);
    first.resize(n+1);
    depth.resize(n+1);
    for ( int i = 2, x; i <= n; ++i )
    {
        is >> x;
        //fscanf(is, "%d", &x);
        G[x].push_back(i);
    }
}
void Euler(int x, int d)
{
    euler.push_back(x);
    depth[x] = d;
    first[x] = euler.size() - 1;
    for ( auto it : G[x] )
    {
        Euler(it, d+1);
        euler.push_back(x);
    }
}
void Preprocesare()
{
    K.resize(nr+1);
    for ( int i = 2; i <= nr; ++i )
        K[i] = 1 + K[i/2];
}

void RMQ()
{
    for ( int i = 1; i <= nr; ++i )
        M[i][0] = i;
    for ( int j = 1; 1 << j <= nr; ++j )
        for ( int i = 0; i + (1<<j) - 1  <= nr; ++i )
        {
            int p1 = M[i][j-1];
            int p2 = M[i+ (1<< j-1 ) ][j-1];
            if ( depth[euler[p1]] < depth[euler[p2]] )
                M[i][j] = p1;
            else
                M[i][j] = p2;
        }
}
int lca(int x, int y)
{
    x = first[x];
    y = first[y];
    if ( x > y )
    {
        int aux = x;
        x = y;
        y = aux;
    }
    int p = Query(x, y);
    return euler[p];
}
int Query(int i, int j)
{
    int k = K[j-i+1];
    int p1 = M[i][k];
    int p2 = M[j - (1<<k) + 1 ][k];
    if ( depth[euler[p1]] < depth[euler[p2]] )
        return p1;
    return p2;
}