Cod sursa(job #1098754)

Utilizator Theorytheo .c Theory Data 5 februarie 2014 03:34:57
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 1.89 kb
#include <fstream>
#include <vector>

using namespace std;

ifstream fin("lca.in");
ofstream fout("lca.out");

const int NMAX = 100009;

int N; int T[NMAX]; vector<int> G[NMAX];int M; int level[NMAX * 2]; int euler[NMAX * 2]; int first[NMAX];

int A[1 << 19]; int min_ind;


void read() {

    fin >> N >> M;

    for(int i = 2; i <= N; ++i) {
        int nod; fin >> nod;
        T[i] = nod;
        G[nod].push_back(i);
    }
}

void dfs(int nod, int le) {


    euler[++euler[0]] = nod;
    level[euler[0]] = le;
    first[nod] = euler[0];

    for(unsigned i = 0; i < G[nod].size(); ++i) {

        dfs(G[nod][i], le + 1);
        euler[++euler[0]] = nod;
        level[euler[0]] = le;

    }
}

void update(int nod, int st, int dr, const int &pos) {

    if(st == dr) {

        A[nod] = pos;
        return ;
    }

    int mid = (st + dr) / 2;

    if(pos <= mid) update(nod * 2, st, mid, pos);
    else update(nod * 2 + 1, mid + 1, dr, pos);

    A[nod] = A[nod * 2];
    if(level[A[nod * 2 + 1]] < level[A[nod]])
        A[nod] = A[nod * 2 + 1];
}

void query(int nod, int st, int dr, const int &pos_st, const int& pos_dr) {

    if(pos_st <= st && dr <= pos_dr) {

        if(!min_ind || level[A[nod]] < level[min_ind]){
                min_ind = A[nod];
        }
        return ;
    }

    int mid = (st + dr) / 2;

    if(pos_st <= mid) query(nod * 2, st , mid, pos_st, pos_dr);

    if(mid < pos_dr) query(nod * 2 + 1, mid + 1, dr, pos_st, pos_dr);

}

int main() {

    read();
    dfs(1, 0);
    for(int i = 1; i <= euler[0]; ++i) {
        update(1, 1, euler[0], i);
    }

    level[0] = (1<<30);
    while(M--) {

        int X; int Y; fin >> X >> Y;
        min_ind = 0;

        query(1, 1, euler[0], min(first[X], first[Y]), max(first[Y], first[X]));
        fout << euler[min_ind] << '\n';

    }

    return 0;
}