Cod sursa(job #543525)

Utilizator zizou_adyIacov Adrian zizou_ady Data 28 februarie 2011 10:50:57
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 1.98 kb
#include <vector>
#include <fstream>
#include <cmath>
using namespace std;
 
#define DIM 100001

FILE *fin = fopen("lca.in" , "r"),
		*fout = fopen("lca.out" , "w");

int t[DIM];
bool s[DIM];
 
int r[2*DIM-1][18];
 
vector <vector <int> > G;
int niv_poz[DIM];
int euler[2*DIM-1];
 
int niv[2*DIM];
int m, n, p;

int rez;
 
void Read();
int RMQ(int i,int j);
void DF(int i, int l);
void Solve();
 
int main()
{
    Read();
	fclose(fin);
	fclose(fout);
    return 0;
}
 
void Read()
{
	fscanf(fin, "%d %d", &n, &m);
    G.resize(n+1);
    t[1] = 0;
    for (int i = 2; i <= n; ++i)
    {
        fscanf(fin, "%d", t + i);
        G[t[i]].push_back(i);
    }
    DF(1, 0);
    Solve();
    for (int i = 1; i <= m; ++i)
    {
        int x, y;
        fscanf(fin, "%d %d", &x, &y);
        if (niv_poz[x] > niv_poz[y])
		{
			rez = RMQ(niv_poz[y] , niv_poz[x]);
			fprintf(fout, "%d\n", rez);
		}
        else
		{
            rez = RMQ(niv_poz[x] , niv_poz[y]);
			fprintf(fout, "%d\n", rez);
		}
    }
}
 
void DF(int i, int l)
{
    s[i] = true;
    niv[++p] = l;
    euler[p] = i;
    niv_poz[i] = p;
    for (int j = 0; j < G[i].size(); ++j)
    {
        if (!s[G[i][j]])
        {
            s[G[i][j]] = true;
            int k = G[i][j];
            DF(k, l+1);
            niv[++p] = l;
            euler[p] = i;
        }
    }
}
 
void Solve()
{
    for (int i = 1; i <= 2*n-1; ++i)
        r[i][0] = i;
    for (int j = 1; 1 << j  <= 2*n - 1; ++j)
        for (int i = 1; i + (1 << j) - 1 <= 2*n -1; ++i)
        {
            if (niv[r[i][j - 1]] < niv[r[i + (1 << (j - 1))][j - 1]])
                r[i][j] = r[i][j - 1];
            else
                r[i][j] = r[i + (1 << (j - 1))][j - 1];
        }
}
 
int RMQ(int i, int j)
{
    int k =(int) log2(j-i + 1);
    if (niv[r[i][k]] <= niv[r[j - (1 << k) + 1][k]])
        return euler[r[i][k]];
    else
        return euler[r[j - (1 << k) + 1][k]];
}