Cod sursa(job #996017)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 10 septembrie 2013 18:37:01
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.62 kb
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

class Tree {
  public:
    Tree(const int V = 0, const int root = 0) {
        this->V = V;
        this->root = root;
        G = vector< vector<int> >(V, vector<int>());
    }

    int Size() const {
        return V;
    }

    vector<int> &Adjacent(const int x) {
        return G[x];
    }

    void AddEdge(const int x, const int y) {
        G[x].push_back(y);
        G[y].push_back(x);
    }

    vector<int> GetNodeLevels() const {
        vector<int> levels = vector<int>(V, -1);
        levels[root] = 0;
        LevelDFS(root, levels);
        return levels;
    }

    vector<int> GetEulerOrder() const {
        vector<int> euler;
        EulerDFS(root, NIL, euler);
        return euler;
    }

  private:
    static const int NIL = -1;

    int V, root;
    vector< vector<int> > G;

    void LevelDFS(const int x, vector<int> &levels) const {
        for (const auto &y: G[x]) {
            if (levels[y] == -1) {
                levels[y] = levels[x] + 1;
                LevelDFS(y, levels);
            }
        }
    }

    void EulerDFS(const int x, const int father, vector<int> &euler) const {
        euler.push_back(x);
        for (const auto &y: G[x]) {
            if (y != father) {
                EulerDFS(y, x, euler);
                euler.push_back(x);
            }
        }
    }
};

template<class Type>
class RMQ {
  public:
    RMQ(const vector<Type> &values) {
        this->values = values;
        size = int(values.size());
        log2 = vector<int>(size + 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 <= log2[size]; ++step) {
            data[step] = vector<int>(size - (1 << step) + 1);
            for (int i = 0; i + (1 << step) <= size; ++i) {
                if (values[data[step - 1][i]] < values[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 Query(const int left, const int right) const {
        int step = log2[right - left + 1];
        if (values[data[step][left]] < values[data[step][right - (1 << step) + 1]])
            return data[step][left];
        else
            return data[step][right - (1 << step) + 1];
    }

  private:
    int size;
    vector<int> log2;
    vector< vector<int> > data;
    vector<Type> values;
};

int main() {
    ifstream cin("lca.in");
    ofstream cout("lca.out");
    int v, q;
    cin >> v >> q;
    Tree T = Tree(v, 0);
    for (int x = 2; x <= v; ++x) {
        int y;
        cin >> y;
        T.AddEdge(x - 1, y - 1);
    }
    vector<int> euler = T.GetEulerOrder(), first = vector<int>(v, -1), levels = T.GetNodeLevels();
    vector<int> eulerLevels = vector<int>(int(euler.size()));
    for (int i = 0; i < int(euler.size()); ++i) {
        if (first[euler[i]] == -1)
            first[euler[i]] = i;
        eulerLevels[i] = levels[euler[i]];
    }
    RMQ<int> rmq = RMQ<int>(eulerLevels);
    for (; q > 0; --q) {
        int x, y;
        cin >> x >> y;
        if (first[y - 1] < first[x - 1])
            swap(x, y);
        cout << euler[rmq.Query(first[x - 1], first[y - 1])] + 1 << "\n";
    }
    cin.close();
    cout.close();
    return 0;
}