Cod sursa(job #1974825)

Utilizator hanganflorinHangan Florin hanganflorin Data 29 aprilie 2017 01:14:20
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.49 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;
vector<vector<int> > G;
vector<int> euler, depth, first, rmq;

void Read();
void Euler(int x, int d = 0);
void Rmq(int nod, int st, int dr);
int Query(int nod, int st, int dr, int p1, int p2);
int lca(int x, int y);

int main()
{
    Read();
    Euler(1);
    rmq.resize(4*euler.size() + 1);
    Rmq(1, 0, euler.size()-1);
    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 Rmq(int nod, int st, int dr)
{
    if ( st == dr )
    {
        rmq[nod] = euler[st];
        return;
    }
    int m = ( st + dr ) / 2;
    Rmq(nod*2, st, m);
    Rmq(nod*2+1, m+1, dr);
    if ( depth[rmq[nod*2] ] < depth[rmq[nod*2+1] ]  )
        rmq[nod] = rmq[nod*2];
    else
        rmq[nod] = rmq[nod*2+1];
}
int Query(int nod, int st, int dr, int p1, int p2)
{
    if ( p1 <= st && p2 >= dr )
        return rmq[nod];
    int m = (st + dr)/2;
    int v1 = -1, v2 = -1;
    if ( p1 <= m )
        v1 = Query(nod*2, st, m, p1, p2);
    if ( m < p2 )
        v2 = Query(nod*2+1, m+1, dr, p1, p2);
    if ( v1 == -1 )
        return v2;
    if ( v2 == -1 )
        return v1;
    if ( depth[v1] < depth[v2] )
        return v1;
    return v2;
}
int lca(int x, int y)
{
    x = first[x];
    y = first[y];
    if ( x > y )
    {
        int aux = x;
        x = y;
        y = aux;
    }
    /*
    int nod, mn = 99999999;
    for ( int i = x; i <= y; ++i )
    {
        if ( depth[euler[i]] < mn )
        {
            mn = depth[euler[i]];
            nod = euler[i];
        }
    }
    return nod;
    */
    return Query(1, 0, euler.size()-1, x, y);
}