Cod sursa(job #2315244)

Utilizator aturcsaTurcsa Alexandru aturcsa Data 9 ianuarie 2019 17:12:49
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.09 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>
#include <ctype.h>

using namespace std;

class InParser {
private:
	FILE *fin;
	char *buff;
	int sp;

	char read_ch() {
		++sp;
		if (sp == 4096) {
			sp = 0;
			fread(buff, 1, 4096, fin);
		}
		return buff[sp];
	}

public:
	InParser(const char* nume) {
		fin = fopen(nume, "r");
		buff = new char[4096]();
		sp = 4095;
	}

	InParser& operator >> (int &n) {
		char c;
		while (!isdigit(c = read_ch()) && c != '-');
		int sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}

	InParser& operator >> (long long &n) {
		char c;
		n = 0;
		while (!isdigit(c = read_ch()) && c != '-');
		long long sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}
};

int k,p;
ofstream fo("lca.out");
vector <int> D[100001];
int n,q;
int ne,E[300001];
int FIRST[100001];
int LEVEL[100001];
int T[300001][20];

int query(int st, int dr)
/// returneaza varful de nivel minim care apare
/// intre E[st] si E[dr];
{
    if (st>dr)
        swap(st,dr);
    int rez;
    rez=E[st];
    for (int i=k;i>=0;i--)
        if (st+(1<<i)-1<=dr)
        {
            if (LEVEL[rez]>LEVEL[T[st][i]])
                rez=T[st][i];
            st=st+(1<<i);
        }
    return rez;
}

void lvl(int nod,int level)
{
    LEVEL[nod]=level;
    vector <int> :: iterator it;
    for (it=D[nod].begin(); it!=D[nod].end(); it++)
        lvl(*it,level+1);
}

void euler(int nod)
{
    vector <int> :: iterator it;
    if (D[nod].size()==0)
    {
        ne++;
        E[ne]=nod;
        if(FIRST[nod]==0)
            FIRST[nod]=ne;
    }
    else
    {
        ne++;
        E[ne]=nod;
        if(FIRST[nod]==0)
            FIRST[nod]=ne;
        for (it=D[nod].begin(); it!=D[nod].end(); it++)
        {
            euler(*it);
            ne++;
            E[ne]=nod;
            if(FIRST[nod]==0)
                FIRST[nod]=ne;
        }
    }

}




int main()
{
    InParser fi("file.in");
    fi>>n>>q;
    for(int i=2; i<=n; i++)
    {
        int a;
        fi>>a;
        D[a].push_back(i);
    }
    euler(1);
    lvl(1,0);
    /// se construieste sparse table pentru E
    /// k este indicele ultimei coloane din T
    k=0;
    p=1;
    while (p*2<=ne)
    {
        k++;
        p=p*2;
    }
    /// se construieste sparse table
    for (int i=1; i<=ne; i++)
        T[i][0]=E[i];
    for (int j=1; j<=k; j++)
        for (int i=1; i<=ne-(1<<j)+1; i++)
            if (LEVEL[T[i][j-1]]<LEVEL[T[i+(1<<(j-1))][j-1]])
                T[i][j]=T[i][j-1];
            else
                T[i][j]=T[i+(1<<(j-1))][j-1];
    /// se raspunde la intrebari
    for (int qu=1; qu<=q; qu++)
    {
        int a,b;
        fi>>a>>b;
        fo<<query(FIRST[a],FIRST[b])<<"\n";
    }
    fo.close();
    return 0;
}