Cod sursa(job #1163935)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 1 aprilie 2014 18:47:08
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3 kb
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

const int NIL = -1;

template<class Type, class Compare>
class RMQ {
  public:
    RMQ(const vector<Type> &_objects, Compare _compare):
      objects(_objects),
      compare(_compare),
      log2(int(_objects.size()) + 1, -1),
      data(vector< vector<int> >()) {
        log2[1] = 0;
        for (int i = 2; i <= Size(); ++i)
            log2[i] = log2[i / 2] + 1;
        data = vector< vector<int> >(log2[Size()] + 1, vector<int>());
        data[0] = vector<int>(Size());
        for (int i = 0; i < Size(); ++i)
            data[0][i] = i;
        for (int step = 1; step < int(data.size()); ++step) {
            data[step] = vector<int>(Size() - (1 << step) + 1);
            for (int i = 0; i + (1 << step) - 1 < Size(); ++i) {
                if (compare(objects[data[step - 1][i]], objects[data[step - 1][i + (1 << (step - 1))]]))
                    data[step][i] = data[step - 1][i];
                else
                    data[step][i] = data[step - 1][i + (1 << (step - 1))];
            }
        }
    }

    int Size() const {
        return int(objects.size());
    }

    Type Object(const int index) const {
        return objects[index];
    }

    int QueryIndex(const int from, const int to) const {
        int step = log2[to - from + 1];
        if (compare(objects[data[step][from]], objects[data[step][to - (1 << step) + 1]]))
            return data[step][from];
        else
            return data[step][to - (1 << step) + 1];
    }

  private:
    vector<Type> objects;
    Compare compare;
    vector<int> log2;
    vector< vector<int> > data;
};

vector< vector<int> > Tree;
int V, Root, Q;
vector<int> Levels, Euler, First;

class Compare {
  public:
    int operator()(const int a, const int b) const {
        return Levels[a] < Levels[b];
    }
};

void DFS(const int x) {
    First[x] = int(Euler.size());
    Euler.push_back(x);
    for (vector<int>::const_iterator y = Tree[x].begin(); y != Tree[x].end(); ++y) {
        Levels[*y] = Levels[x] + 1;
        DFS(*y);
        Euler.push_back(x);
    }
}

void Preprocess() {
    Levels = First = vector<int>(V, -1);
    Euler = vector<int>();
    Levels[Root] = 0;
    DFS(Root);
}

inline void AddEdge(const int from, const int to) {
    Tree[from].push_back(to);
}

int main() {
    ifstream cin("lca.in");
    ofstream cout("lca.out");
    cin >> V >> Q;
    Tree = vector< vector<int> >(V, vector<int>());
    Root = 0;
    for (int x = 2; x <= V; ++x) {
        int y;
        cin >> y;
        AddEdge(y - 1, x - 1);
    }
    Preprocess();
    RMQ<int, Compare> rmq = RMQ<int, Compare>(Euler, Compare());
    for (; Q > 0; --Q) {
        int x, y;
        cin >> x >> y;
        if (First[y - 1] < First[x - 1])
            swap(x, y);
        cout << rmq.Object(rmq.QueryIndex(First[x - 1], First[y - 1])) + 1 << "\n";
    }
    cin.close();
    cout.close();
    return 0;
}