Cod sursa(job #1525217)

Utilizator andrei_diaconuAndrei Diaconu andrei_diaconu Data 14 noiembrie 2015 20:58:13
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.95 kb
#include <fstream>
#include <vector>

#define NMax 100010

using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");

int nodes, queries, eulPath[2*NMax], k, lvl[2*NMax], firstOc[NMax], rmq[18][2*NMax], lg[2*NMax];
bool mark[NMax];
vector<int> tree[NMax];

int getMin(int a, int b)
{
    if (a < b)
        return a;
    return b;
}

int getMax(int a, int b)
{
    if (a > b)
        return a;
    return b;
}

void DFS(int node, int level)
{
    k++;
    eulPath[k] = node;
    lvl[k] = level;
    
    for (vector<int>::iterator it = tree[node].begin(); it != tree[node].end(); it++) {
        DFS(*it, level+1);
        eulPath[++k] = node;
        lvl[k] = level;
    }
}

void preprocRMQ()
{
    for (int i=2; i<=k; i++)
        lg[i] = lg[i/2] + 1;
    
    for (int i=1; i<=lg[k]; i++) {
        int power = 1<<(i-1);
        
        for (int j=1; j <= k - power; j++) {
            rmq[i][j] = rmq[i-1][j];
            
            if (lvl[ rmq[i][j] ] > lvl[ rmq[i-1][j + power] ])
                rmq[i][j] = rmq[i-1][j + power];
        }
    }
}

int main()
{
    f>>nodes>>queries;
    
    int node;
    for (int i=2; i<=nodes; i++) {
        f>>node;
        
        tree[node].push_back(i);
    }
    
    DFS(1, 1);
    
    for (int i=1; i<=k; i++) {
        int crtNode = eulPath[i];
        if (!mark[crtNode]) {
            firstOc[crtNode] = i;
            mark[crtNode] = true;
        }
    }
    
    for (int i=1; i<=k; i++)
        rmq[0][i] = i;
    
    preprocRMQ();
    
    int node1, node2;
    for (int i=1; i<=queries; i++) {
        f>>node1>>node2;
        int left = getMin(firstOc[node1], firstOc[node2]);
        int right = getMax(firstOc[node1], firstOc[node2]);
        
        int llg = lg[right - left];
        
        if (lvl[rmq[llg][left]] < lvl[rmq[llg][right - (1<<llg) + 1]])
            g<<eulPath[rmq[llg][left]]<<"\n";
        else
            g<<eulPath[rmq[llg][right - (1<<llg) + 1]]<<"\n";
        
    }
    
    return 0;
}