Cod sursa(job #1512805)

Utilizator serbanSlincu Serban serban Data 28 octombrie 2015 17:50:23
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.72 kb
#include <bits/stdc++.h>

using namespace std;

int t[100005], n, start;
bool viz[100005];
vector<int> L[100005];

vector< pair<int, int> > euler; //200 005
int first[100005];

FILE *g = fopen("lca.out", "w");

void dfs(int where, int level) {
    first[where] = euler.size() - 1;
    for(int i = 0; i < L[where].size(); i ++) {
        euler.push_back(make_pair(L[where][i], level + 1));
        dfs(L[where][i], level + 1);
        euler.push_back(make_pair(where, level));
    }
}

int M[200005][20];
int lca(int a, int b) {
    if(a > b) {
        int aux = a;
        a = b;
        b = aux;
    }
    int k = log2(b - a + 1);
    int ret;
    if(euler[M[a][k]].second < euler[M[b - (1 << k) + 1][k]].second)
        ret = M[a][k];
    else ret = M[b - (1 << k) + 1][k];
    return euler[ret].first;
}

int main()
{
    FILE *f = fopen("lca.in", "r");

    int m, x, y;
    fscanf(f, "%d %d", &n, &m);
    for(int i = 2; i <= n; i ++) {
        fscanf(f, "%d", &t[i]);
        viz[i] = true;
        L[t[i]].push_back(i);
    }
    for(int i = 1; i <= n; i ++) {
        if(!viz[i])
            start = i;
    }

    euler.push_back(make_pair(start, 0));
    dfs(start, 0);
    n = euler.size();
    for(int i = 0; i < n; i ++)
        M[i][0] = i;
    for(int j = 1; 1 << j < n; j ++) {
        for(int i = 0; i + (1 << j) - 1 < n; i ++) {
            if(euler[M[i][j - 1]].second >= euler[M[i + (1 << (j - 1))][j - 1]].second)
                M[i][j] = M[i + (1 << (j - 1))][j - 1];
            else M[i][j] = M[i][j - 1];
        }
    }

    for(int i = 1; i <= m; i ++) {
        fscanf(f, "%d %d", &x, &y);
        fprintf(g, "%d\n", lca(first[x], first[y]));
    }
    return 0;
}