Pagini recente » Borderou de evaluare (job #596564) | Cod sursa (job #1988578) | Borderou de evaluare (job #2010144) | Borderou de evaluare (job #2012777) | Cod sursa (job #2501561)
#include <fstream>
#include <vector>
template <typename T>
class RmqVector {
public:
explicit RmqVector() : RmqVector(0) {}
explicit RmqVector(int size) {
mins_.resize(size, {T()});
logs_.resize(size + 1, 0);
for (int i = 2; i <= size; i += 1) {
logs_[i] = logs_[i / 2] + 1;
}
}
void set(int pos, const T &value) {
mins_[pos][0] = value;
}
T get(int left, int right) const {
int len = right - left + 1;
int log = logs_[len];
int mid = left + (1 << log) - 1;
return std::min(mins_[mid][log], mins_[right][log]);
}
void preprocess() {
for (size_t i = 1; i < mins_.size(); i += 1) {
for (int log = 0; log < logs_[i + 1]; log += 1) {
auto mid = i - (1 << log);
auto min_left = mins_[mid][log];
auto min_right = mins_[i][log];
auto new_min = std::min(min_left, min_right);
mins_[i].push_back(new_min);
}
}
}
private:
std::vector<std::vector<T>> mins_;
std::vector<int> logs_;
};
class EulerData
{
public:
explicit EulerData(int nodes) {
node_by_order_.resize(nodes, -1);
order_by_node_.resize(nodes, -1);
first_pos_in_tour_.resize(nodes, -1);
int tour_size = 2 * (nodes - 1) + 1;
tour_ = RmqVector<int>(tour_size);
next_order_ = 0;
tour_pos_ = 0;
}
void solveRmq() {
tour_.preprocess();
}
int lca(int a, int b) const {
int pos_a = first_pos_in_tour_[a];
int pos_b = first_pos_in_tour_[b];
int left = std::min(pos_a, pos_b);
int right = std::max(pos_a, pos_b);
int order_lca = tour_.get(left, right);
return node_by_order_[order_lca];
}
void addNode(int node) {
if (first_pos_in_tour_[node] == -1) {
first_pos_in_tour_[node] = tour_pos_;
order_by_node_[node] = next_order_;
node_by_order_[next_order_] = node;
next_order_ += 1;
}
tour_.set(tour_pos_, order_by_node_[node]);
tour_pos_ += 1;
}
private:
std::vector<int> node_by_order_;
std::vector<int> order_by_node_;
std::vector<int> first_pos_in_tour_;
RmqVector<int> tour_;
int next_order_;
int tour_pos_;
};
using Tree = std::vector<std::vector<int>>;
void eulerTour(const Tree &tree, int node, int father, EulerData &euler)
{
euler.addNode(node);
for (const auto &son : tree[node]) {
if (son != father) {
eulerTour(tree, son, node, euler);
euler.addNode(node);
}
}
}
EulerData eulerTour(const Tree &tree) {
int nodes = tree.size();
EulerData euler(nodes);
eulerTour(tree, 0, -1, euler);
euler.solveRmq();
return euler;
}
std::vector<int> lca(const Tree &tree,
const std::vector<std::pair<int, int>> &queries) {
auto euler = eulerTour(tree);
std::vector<int> answers;
for (const auto &q : queries) {
int a = q.first;
int b = q.second;
answers.push_back(euler.lca(a, b));
}
return answers;
}
int main()
{
std::ifstream fin("lca.in");
std::ofstream fout("lca.out");
int nodes, tests;
fin >> nodes >> tests;
std::vector<std::vector<int>> tree(nodes);
for (int i = 1; i < nodes; i += 1) {
int father;
fin >> father;
tree[father - 1].push_back(i);
tree[i].push_back(father - 1);
}
std::vector<std::pair<int, int>> queries(tests);
for (auto &q : queries) {
fin >> q.first >> q.second;
q.first -= 1;
q.second -= 1;
}
auto res = lca(tree, queries);
for (const auto &node : res) {
fout << node + 1 << "\n";
}
return 0;
}