Cod sursa(job #1934852)

Utilizator MaligMamaliga cu smantana Malig Data 21 martie 2017 21:14:02
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.79 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <climits>
#include <queue>
#include <cmath>

using namespace std;
ifstream in("lca.in");
ofstream out("lca.out");

const int NMax = 1e5 + 5;
const int inf = 1e9;
#define foreach(V) for(typeof (V).begin() it = (V).begin(); it != (V).end(); ++it)

int N,M,nrEuler;
int euler[2*NMax],poz[NMax],depth[NMax],
    lg[2*NMax],mn[2*NMax][20];

vector<int> v[NMax];

void doEuler(int,int);

int main() {
    in>>N>>M;

    int mx = 0;
    for (int i=2;i<=N;++i) {
        int dad;
        in>>dad;
        v[dad].push_back(i);

        if (mx < dad) {
            mx = dad;
        }
    }
    //cout<<mx<<'\n';

    doEuler(1,1);
    //cout<<nrEuler<<'\n';

    for (int i=1;i<=nrEuler;++i) {
        int n1 = euler[i-1],
            n2 = euler[i],
            d1 = depth[n1],
            d2 = depth[n2];
        if (abs(d1-d2) > 1 || d2 <= 0) {
            cout<<euler[i]<<'\n';
        }
    }

    /*
    for (int i=1;i<=nrEuler;++i) {
        out<<i<<' ';
    }
    out<<'\n';

    for (int i=1;i<=nrEuler;++i) {
        out<<euler[i]<<' ';
    }
    out<<"\n\n";

    for (int i=1;i<=N;++i) {
        out<<i<<' ';
    }
    out<<'\n';

    for (int i=1;i<=N;++i) {
        out<<depth[i]<<' ';
    }
    out<<'\n';

    for (int i=1;i<=N;++i) {
        out<<poz[i]<<' ';
    }
    out<<'\n';
    //*/

    lg[1] = 0;
    mn[1][0] = euler[1];
    for (int i=2;i<=nrEuler;++i) {
        lg[i] = lg[i/2] + 1;
        //out<<i<<' '<<lg[i]<<'\n';
        mn[i][0] = euler[i];
    }
    //out<<"\n\n\n";

    for (int p=1;(1<<p) <= nrEuler;++p) {
        for (int i=1;i + (1<<p) - 1 <= nrEuler;++i) {
            int nod1 = mn[i][p-1],
                nod2 = mn[i + (1<<(p-1))][p-1];
            if (depth[nod1] < depth[nod2]) {
                mn[i][p] = nod1;
            }
            else {
                mn[i][p] = nod2;
            }
        }
    }

    /*
    for (int i=2;i<=nrEuler;++i) {
        out<<i<<' '<<lg[i]<<'\n';
    }
    out<<"\n\n\n";
    */

    while (M--) {
        int a,b;
        in>>a>>b;
        if (poz[a]>poz[b]) {
            swap(a,b);
        }

        int i = poz[a], j = poz[b],
            p = lg[j-i+1],
            nod1 = mn[i][p],
            nod2 = mn[j - (1<<p) + 1][p];

        int ans;
        if (depth[nod1] < depth[nod2]) {
            ans = nod1;
        }
        else {
            ans = nod2;
        }

        out<<ans<<'\n';
    }

    return 0;
}

void doEuler(int x,int d) {
    euler[++nrEuler] = x;
    poz[x] = nrEuler;
    depth[x] = d;

    int lim = v[x].size();
    for (int i=0;i<lim;++i) {
        int son = v[x][i];
        doEuler(son,d+1);
        euler[++nrEuler] = x;
    }
}